From a7f58b2026dc4246e3cd83a14c0d9ab63023cd63 Mon Sep 17 00:00:00 2001 From: Paul Allen Date: Tue, 2 Aug 2016 11:19:41 -0700 Subject: [PATCH 01/25] split the wsman apis into client/server shared libraries --- .../engine/remoting/fanin/WSManNativeAPI.cs | 58 ++++++++++--------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/src/System.Management.Automation/engine/remoting/fanin/WSManNativeAPI.cs b/src/System.Management.Automation/engine/remoting/fanin/WSManNativeAPI.cs index 6869f44ae..aa12e3d41 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/WSManNativeAPI.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/WSManNativeAPI.cs @@ -2299,9 +2299,11 @@ namespace System.Management.Automation.Remoting.Client #region DllImports ClientAPI #if !UNIX - internal const string WSManApiDll = @"WsmSvc.dll"; + internal const string WSManClientApiDll = @"WsmSvc.dll"; + internal const string WSManProviderApiDll = @"WsmSvc.dll"; #else - internal const string WSManApiDll = @"libpsrpomiprov"; + internal const string WSManClientApiDll = @"libpsrpclient"; + internal const string WSManProviderApiDll = @"libpsrpomiprov"; #endif /// @@ -2315,7 +2317,7 @@ namespace System.Management.Automation.Remoting.Client /// /// /// - [DllImport(WSManNativeApi.WSManApiDll, SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern int WSManInitialize(int flags, [In, Out] ref IntPtr wsManAPIHandle); @@ -2329,7 +2331,7 @@ namespace System.Management.Automation.Remoting.Client /// /// /// - [DllImport(WSManNativeApi.WSManApiDll, SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern int WSManDeinitialize(IntPtr wsManAPIHandle, int flags); /// @@ -2348,7 +2350,7 @@ namespace System.Management.Automation.Remoting.Client /// /// /// - [DllImport(WSManNativeApi.WSManApiDll, SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern int WSManCreateSession(IntPtr wsManAPIHandle, [MarshalAs(UnmanagedType.LPWStr)]string connection, int flags, @@ -2364,7 +2366,7 @@ namespace System.Management.Automation.Remoting.Client /// /// /// - [DllImport(WSManNativeApi.WSManApiDll, SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern void WSManCloseSession(IntPtr wsManSessionHandle, int flags); @@ -2389,7 +2391,7 @@ namespace System.Management.Automation.Remoting.Client } } - [DllImport(WSManNativeApi.WSManApiDll, SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern int WSManSetSessionOption(IntPtr wsManSessionHandle, WSManSessionOption option, IntPtr data); @@ -2404,7 +2406,7 @@ namespace System.Management.Automation.Remoting.Client /// An int (DWORD) data. /// /// - [DllImport(WSManNativeApi.WSManApiDll, SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern void WSManGetSessionOptionAsDword(IntPtr wsManSessionHandle, WSManSessionOption option, out int value); @@ -2460,7 +2462,7 @@ namespace System.Management.Automation.Remoting.Client return returnval; } - [DllImport(WSManNativeApi.WSManApiDll, SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, SetLastError = false, CharSet = CharSet.Unicode)] private static extern int WSManGetSessionOptionAsString(IntPtr wsManSessionHandle, WSManSessionOption option, int optionLength, @@ -2510,7 +2512,7 @@ namespace System.Management.Automation.Remoting.Client openContent, asyncCallback, ref shellOperationHandle); } - [DllImport(WSManNativeApi.WSManApiDll, EntryPoint = "WSManCreateShellEx", SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, EntryPoint = "WSManCreateShellEx", SetLastError = false, CharSet = CharSet.Unicode)] private static extern void WSManCreateShellExInternal(IntPtr wsManSessionHandle, int flags, [MarshalAs(UnmanagedType.LPWStr)]string resourceUri, @@ -2532,7 +2534,7 @@ namespace System.Management.Automation.Remoting.Client /// /// /// - [DllImport(WSManNativeApi.WSManApiDll, EntryPoint = "WSManConnectShell", SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, EntryPoint = "WSManConnectShell", SetLastError = false, CharSet = CharSet.Unicode)] internal static extern void WSManConnectShellEx(IntPtr wsManSessionHandle, int flags, [MarshalAs(UnmanagedType.LPWStr)]string resourceUri, @@ -2550,7 +2552,7 @@ namespace System.Management.Automation.Remoting.Client /// /// /// - [DllImport(WSManNativeApi.WSManApiDll, EntryPoint = "WSManDisconnectShell", SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, EntryPoint = "WSManDisconnectShell", SetLastError = false, CharSet = CharSet.Unicode)] internal static extern void WSManDisconnectShellEx(IntPtr wsManSessionHandle, int flags, IntPtr disconnectInfo, @@ -2562,13 +2564,13 @@ namespace System.Management.Automation.Remoting.Client /// /// /// - [DllImport(WSManNativeApi.WSManApiDll, EntryPoint = "WSManReconnectShell", SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, EntryPoint = "WSManReconnectShell", SetLastError = false, CharSet = CharSet.Unicode)] internal static extern void WSManReconnectShellEx(IntPtr wsManSessionHandle, int flags, IntPtr asyncCallback); - [DllImport(WSManNativeApi.WSManApiDll, EntryPoint = "WSManReconnectShellCommand", SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, EntryPoint = "WSManReconnectShellCommand", SetLastError = false, CharSet = CharSet.Unicode)] internal static extern void WSManReconnectShellCommandEx(IntPtr wsManCommandHandle, int flags, IntPtr asyncCallback); @@ -2597,7 +2599,7 @@ namespace System.Management.Automation.Remoting.Client /// An out parameter referening a WSMan shell operation handle /// for this command. /// - [DllImport(WSManNativeApi.WSManApiDll, EntryPoint = "WSManRunShellCommandEx", SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, EntryPoint = "WSManRunShellCommandEx", SetLastError = false, CharSet = CharSet.Unicode)] internal static extern void WSManRunShellCommandEx(IntPtr shellOperationHandle, int flags, [MarshalAs(UnmanagedType.LPWStr)] @@ -2610,7 +2612,7 @@ namespace System.Management.Automation.Remoting.Client ref IntPtr commandOperationHandle); - [DllImport(WSManNativeApi.WSManApiDll, EntryPoint = "WSManConnectShellCommand", SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, EntryPoint = "WSManConnectShellCommand", SetLastError = false, CharSet = CharSet.Unicode)] internal static extern void WSManConnectShellCommandEx(IntPtr shellOperationHandle, int flags, [MarshalAs(UnmanagedType.LPWStr)] @@ -2646,7 +2648,7 @@ namespace System.Management.Automation.Remoting.Client /// /// handle to use to cancel the operation. /// - [DllImport(WSManNativeApi.WSManApiDll, EntryPoint = "WSManReceiveShellOutput", SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, EntryPoint = "WSManReceiveShellOutput", SetLastError = false, CharSet = CharSet.Unicode)] internal static extern void WSManReceiveShellOutputEx(IntPtr shellOperationHandle, IntPtr commandOperationHandle, int flags, @@ -2685,7 +2687,7 @@ namespace System.Management.Automation.Remoting.Client streamData, false, asyncCallback, ref sendOperationHandle); } - [DllImport(WSManNativeApi.WSManApiDll, EntryPoint = "WSManSendShellInput", SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, EntryPoint = "WSManSendShellInput", SetLastError = false, CharSet = CharSet.Unicode)] private static extern void WSManSendShellInputExInternal(IntPtr shellOperationHandle, IntPtr commandOperationHandle, int flags, @@ -2710,7 +2712,7 @@ namespace System.Management.Automation.Remoting.Client /// /// callback to notify when the operation completes. /// - [DllImport(WSManNativeApi.WSManApiDll, SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern void WSManCloseShell(IntPtr shellHandle, int flags, IntPtr asyncCallback); @@ -2726,7 +2728,7 @@ namespace System.Management.Automation.Remoting.Client /// /// callback to notify when the operation completes. /// - [DllImport(WSManNativeApi.WSManApiDll, SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern void WSManCloseCommand(IntPtr cmdHandle, int flags, IntPtr asyncCallback); @@ -2742,7 +2744,7 @@ namespace System.Management.Automation.Remoting.Client /// /// /// - [DllImport(WSManNativeApi.WSManApiDll, EntryPoint = "WSManSignalShell", SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, EntryPoint = "WSManSignalShell", SetLastError = false, CharSet = CharSet.Unicode)] internal static extern void WSManSignalShellEx(IntPtr shellOperationHandle, IntPtr cmdOperationHandle, int flags, @@ -2761,7 +2763,7 @@ namespace System.Management.Automation.Remoting.Client /// /// /// - [DllImport(WSManNativeApi.WSManApiDll, SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern void WSManCloseOperation(IntPtr operationHandle, int flags); /// @@ -2858,7 +2860,7 @@ namespace System.Management.Automation.Remoting.Client /// It cannot be NULL. If both "messageLength" and "message" parameters are 0, the function will return ERROR_INSUFFICIENT_BUFFER /// and "messageLengthUsed" parameter will be set to the number of characters needed, including NULL terminator /// - [DllImport(WSManNativeApi.WSManApiDll, SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManClientApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern int WSManGetErrorMessage(IntPtr wsManAPIHandle, int flags, string languageCode, @@ -2879,7 +2881,7 @@ namespace System.Management.Automation.Remoting.Client /// Specifies the options that are available for retrieval. /// Specifies the result object (WSMAN_DATA). /// - [DllImport(WSManNativeApi.WSManApiDll, SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManProviderApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern int WSManPluginGetOperationParameters( IntPtr requestDetails, int flags, @@ -2895,7 +2897,7 @@ namespace System.Management.Automation.Remoting.Client /// Reports any failure in the operation. Terminates on non-NO_ERROR status. /// XML document containing extra error information. /// - [DllImport(WSManNativeApi.WSManApiDll, SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManProviderApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern int WSManPluginOperationComplete( IntPtr requestDetails, int flags, @@ -2942,7 +2944,7 @@ namespace System.Management.Automation.Remoting.Client /// Specifies the state of the command. It must be set to a value specified by the plugin. /// Only set when the commandState is terminating. /// - [DllImport(WSManNativeApi.WSManApiDll, SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManProviderApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern int WSManPluginReceiveResult( IntPtr requestDetails, int flags, @@ -2961,7 +2963,7 @@ namespace System.Management.Automation.Remoting.Client /// /// Defines the value to pass into all future shell and command operations. Represents either the shell or the command. /// - [DllImport(WSManNativeApi.WSManApiDll, SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManProviderApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern int WSManPluginReportContext( IntPtr requestDetails, int flags, @@ -2974,7 +2976,7 @@ namespace System.Management.Automation.Remoting.Client /// Callback to be executed on shutdown /// /// - [DllImport(WSManNativeApi.WSManApiDll, SetLastError = false, CharSet = CharSet.Unicode)] + [DllImport(WSManNativeApi.WSManProviderApiDll, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern void WSManPluginRegisterShutdownCallback( IntPtr requestDetails, IntPtr shutdownCallback, From 21494be11badbf787acb8bc08d45d7927053e1b6 Mon Sep 17 00:00:00 2001 From: James Truher Date: Wed, 27 Jul 2016 18:37:50 -0700 Subject: [PATCH 02/25] updates from previous PR to incorporate feedback --- docs/testing-guidelines/PesterDoAndDont.md | 28 ++-- docs/testing-guidelines/Testing.md | 106 -------------- docs/testing-guidelines/WritingPesterTests.md | 66 +++++---- docs/testing-guidelines/testing-guidelines.md | 138 +++++++++++++++++- 4 files changed, 186 insertions(+), 152 deletions(-) mode change 100644 => 100755 docs/testing-guidelines/PesterDoAndDont.md delete mode 100644 docs/testing-guidelines/Testing.md mode change 100644 => 100755 docs/testing-guidelines/WritingPesterTests.md mode change 100644 => 100755 docs/testing-guidelines/testing-guidelines.md diff --git a/docs/testing-guidelines/PesterDoAndDont.md b/docs/testing-guidelines/PesterDoAndDont.md old mode 100644 new mode 100755 index 56bcfe857..250e5b6f0 --- a/docs/testing-guidelines/PesterDoAndDont.md +++ b/docs/testing-guidelines/PesterDoAndDont.md @@ -1,23 +1,25 @@ ## Do -1. Name your files .tests.ps1 +1. Name your files .tests.ps1 2. Keep tests simple 1. Test only what you need 2. Reduce dependencies -3. Be sure to tag your Describe blocks with "inner" and "outer" -4. Make sure that Describe/Context/It descriptions are useful +3. Be sure to tag your `Describe` blocks based on their purpose + 1. Tag `CI` indicates that it will be run as part of the continuous integration process. These should be unit test like, and fast. + 2. Tag `Feature` indicates a higher level feature test (we will run these on a regular basis), for example, tests which go to remote resources, or test broader functionality + 3. Tag `Scenario` indicates tests of integration with other features (these will be run on a less regular basis and test even broader functionality than feature tests. +4. Make sure that `Describe`/`Context`/`It` descriptions are useful 1. The error message should not be the place where you describe the test -5. Use "Context" to group tests - 1. Multiple Contexts can help you group your test suite into logical sections -6. Use BeforeAll/AfterAll/BeforeEach/AfterEach instead of custom initiators -7. Use Try-Catch for expected errors and check $_.fullyQualifiedErrorId -8. Loop It blocks for checking multiple properties +5. Use `Context` to group tests + 1. Multiple `Context` blocks can help you group your test suite into logical sections +6. Use `BeforeAll`/`AfterAll`/`BeforeEach`/`AfterEach` instead of custom initiators +7. Use Try-Catch for expected errors and check $_.fullyQualifiedErrorId (don't use `should throw`) +8. Use `-testcases` when iterating over multiple `It` blocks 9. Use code coverage functionality where appropriate -10. Use Mock functionality when you don't have your entire environment -11. Avoid free code in a Describe block +10. Use `Mock` functionality when you don't have your entire environment +11. Avoid free code in a `Describe` block 1. Use `[Before|After][Each|All]` _see Free Code in a Describe block_ ## Don't 1. Have too many evaluations in a single It block - 1. The first "Should" failure will stop that block -2. Don't use "Should" anywhere but within an "It" Block - + 1. The first `Should` failure will stop that block +2. `Should` be used in an `It` Block diff --git a/docs/testing-guidelines/Testing.md b/docs/testing-guidelines/Testing.md deleted file mode 100644 index d322cee69..000000000 --- a/docs/testing-guidelines/Testing.md +++ /dev/null @@ -1,106 +0,0 @@ -# DRAFT - -_I have more questions than answers_ - - -#### Current Test Infrastructure -We currently rely heavily on STEX environment for our testing, and we will continue to do so through the Server2016 release. We -need to use that current infrastructure to continue to test full PowerShell builds; it should be possible to build automation -which takes a full PowerShell build and lay it on an existing lab system, update the appropriate test files and execute -a test pass in the same way that we do with official builds. - -The test artifacts which are applicable to full PowerShell are not universally applicable to Core/Nano/OtherPlatform, we will need -to create tooling which allows us to apply a set of test artifacts to a configuration, and then execute tests. Eventually, we need -to have our CI environment test all the flavors of PowerShell we create. -**Question**: Can AppVeyor/Travis service that need? - - -#### Organization -**Proposal**: Create 3 tiers of testing: - -* Checkin - * These are run as part of the CI process, and should run quickly. How quickly is an open question. We need to determine - the right amount of coverage without spending too much time. It may be that we can improve our coverage here through parallelization - but we have not investigated enough to determine whether it's possible. -* Feature - * the tests which look at corner cases, and stand-alone modules (for example, the archive module tests could fall into this - category) -* Scenario - * these are tests which span features, and determine whether the whole product is working correctly. The current P3 tests fall - largely here - -**Actions**: Decide what goes where. My initial thoughts are to migrate our current TTEST unittests into tier 1 (Checkin) - -**Current Migration Activity** - -We have teams working on migrating tests which are in non-portable frameworks (TTest, Lite1, Lite3, etc) to portable frameworks. -The first effort is to migrate our TTEST cmdlet unit tests to Pester, we should be taking those migrated tests and get them into -SD - -##### Layout -We need to have a reasonable layout of our tests, not sure what that looks like yet. We need to make it -easy to find both feature and test code to reduce our maintainance burden. - -##### Self Hosting -Self-Hosting remains problematic while are still so early in the development phase, but it is _imperative_ -that we dog food as early as possible. This is especially true on the non-Windows platforms where we have made -assumptions about the working environment with regard to a number of issues: -* removal of well known aliases -* case sensitivity of some operations -* coverage -We should be using these non-windows platforms as much as possible to - -======= -# DRAFT - -_I have more questions than answers_ - - -#### Current Test Infrastructure -We currently rely heavily on STEX environment for our testing, and we will continue to do so through the Server2016 release. We -need to use that current infrastructure to continue to test full PowerShell builds; it should be possible to build automation -which takes a full PowerShell build and lay it on an existing lab system, update the appropriate test files and execute -a test pass in the same way that we do with official builds. - -The test artifacts which are applicable to full PowerShell are not universally applicable to Core/Nano/OtherPlatform, we will need -to create tooling which allows us to apply a set of test artifacts to a configuration, and then execute tests. Eventually, we need -to have our CI environment test all the flavors of PowerShell we create. -**Question**: Can AppVeyor/Travis service that need? - - -#### Organization -**Proposal**: Create 3 tiers of testing: - -* Checkin - * These are run as part of the CI process, and should run quickly. How quickly is an open question. We need to determine - the right amount of coverage without spending too much time. It may be that we can improve our coverage here through parallelization - but we have not investigated enough to determine whether it's possible. -* Feature - * the tests which look at corner cases, and stand-alone modules (for example, the archive module tests could fall into this - category) -* Scenario - * these are tests which span features, and determine whether the whole product is working correctly. The current P3 tests fall - largely here - -**Actions**: Decide what goes where. My initial thoughts are to migrate our current TTEST unittests into tier 1 (Checkin) - -**Current Migration Activity** - -We have teams working on migrating tests which are in non-portable frameworks (TTest, Lite1, Lite3, etc) to portable frameworks. -The first effort is to migrate our TTEST cmdlet unit tests to Pester, we should be taking those migrated tests and get them into -SD - -##### Layout -We need to have a reasonable layout of our tests, not sure what that looks like yet. We need to make it -easy to find both feature and test code to reduce our maintainance burden. - -##### Self Hosting -Self-Hosting remains problematic while are still so early in the development phase, but it is _imperative_ -that we dog food as early as possible. This is especially true on the non-Windows platforms where we have made -assumptions about the working environment with regard to a number of issues: -* removal of well known aliases -* case sensitivity of some operations -* coverage -We should be using these non-windows platforms as much as possible to - ->>>>>>> Create Testing.md diff --git a/docs/testing-guidelines/WritingPesterTests.md b/docs/testing-guidelines/WritingPesterTests.md old mode 100644 new mode 100755 index 88c532e78..a60c3a36e --- a/docs/testing-guidelines/WritingPesterTests.md +++ b/docs/testing-guidelines/WritingPesterTests.md @@ -1,9 +1,13 @@ -Because we are planning to continue to extend Pester to support remote/parallel execution, it's important to keep in mind the following when create tests: +### Writing Pester Tests +Note that this document does not replace the documents found in the [Pester](https://github.com/pester/pester "Pester") project. This is just +some quick tips and suggestions for creating Pester tests for this project. The Pester community is vibrant and active, if you have questions +about Pester or creating tests, the [Pester Wiki](https://github.com/pester/pester/wiki) has a lot of great information. + +When creating tests, keep the following in mind: * Tests should not be overly complicated and test too many things * boil down your tests to their essence, test only what you need * Tests should be as simple as they can * Tests should generally not rely on any other test - Examples: Here's the simplest of tests @@ -27,14 +31,28 @@ Describe "One is really one" { } It "1 is really an int" { $i = 1 - $i.GetType().FullName | Should Be System.Int32 + $i.GetType() | Should Be "int" } } ``` -If you are checking for proper errors, do that in a try catch, and then check fully qualified error id +alternatively, you could do the following: +``` +Describe "One is really one" { + It "Compare 1 to 1" { + $a = 1 + $a | Should be 1 + } + It "1 is really an int" { + $i = 1 + $i.GetType() | Should Be ([System.Int32]) + } +} +``` + +If you are checking for proper errors, do that in a `try/catch`, and then check `FullyQualifiedErrorId`. Checking against `FullyQualifiedErrorId` is recommended because it does not change based on culture as an error message might. ``` ... -it "Error should be PathNotFound" { +it "Get-Item on a nonexisting file should have error PathNotFound" { try { get-item "ThisFileCannotPossiblyExist" -ErrorAction Stop @@ -42,8 +60,7 @@ it "Error should be PathNotFound" { } catch { - $_.FullyQualifiedErrorId | - should be "PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand" + $_.FullyQualifiedErrorId | should be "PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand" } } ``` @@ -51,12 +68,10 @@ it "Error should be PathNotFound" { Note that if get-item were to succeed, a different FullyQualifiedErrorId would be thrown and the test will fail because the FQErrorId is wrong. This is the suggested path because Pester wants to check the error message, which will likely not work here because of localized builds, but the FullyQualifiedErrorId is constant regardless of the locale. ### Describe/Context/It - -From an organizational standpoint, a Describe block roughly compares to a LITE3 Test Suite and an It block roughly compares to a LITE3 testcase. Unlike LITE3, individual tests are not prioritized (remember that a test name in Pester is really a descriptive sentence, rather than a name), but a Describe block (TestSuite) may be tagged with a string. -For creation of PowerShell tests, the Describe block is the level of granularity suggested and one of two tags should be used: "Inner" or "Outer". If the tag is not provided, tests in that describe block will be run any time tests are executed. +For creation of PowerShell tests, the Describe block is the level of granularity suggested and one of three tags should be used: "CI", "Feature", or "Scenario". If the tag is not provided, tests in that describe block will be run any time tests are executed. #### Describe -Creates a logical group of tests. All Mocks and TestDrive contents defined within a Describe block are scoped to that Describe ; they will no longer be present when the Describe block exits. A Describe block may contain any number of Context and It blocks. +Creates a logical group of tests. All Mocks and TestDrive contents defined within a Describe block are scoped to that Describe; they will no longer be present when the Describe block exits. A `Describe block may contain any number of Context and It blocks. #### Context Provides logical grouping of It blocks within a single Describe block. Any Mocks defined inside a Context are removed at the end of the Context scope, as are any files or folders added to the TestDrive during the Context block's execution. Any BeforeEach or AfterEach blocks defined inside a Context also only apply to tests within that Context . @@ -92,16 +107,7 @@ Describe "Add-Footer" { When this test completes, the contents of the TestDrive PSDrive will be removed. #### Parameter Generation -This is quite a bit different from LITE3, but still possible, see the following: - ``` -Describe "A test" { -function Test-Xor { - param ($a, $b, $ExpectedResult) - It ("Applies XOR to inputs {0} and {1}" -f $a, $b) { - $a -xor $b | Should be $ExpectedResult - } -} $testCases = @( @{ a = 0; b = 1; ExpectedResult = 1 } @@ -109,13 +115,16 @@ $testCases = @( @{ a = 1; b = 1; ExpectedResult = 0 } @{ a = 0; b = 0; ExpectedResult = 0 } ) - foreach ($testCase in $testCases) { - Test-Xor @testCase - } + +Describe "A test" { + It " -xor should be " -testcase $testcases { + param ($a, $b, $ExpectedResult) + $a -xor $b | Should be $ExpectedResult + } } ``` -You can construct the values to pass as parameters, including the expected value, and use that iteratively in a loop. Note the location of the `It` block +You can also construct loops and pass values as parameters, including the expected value, but Pester does this for you. #### Mocking Mocks the behavior of an existing command with an alternate implementation. This creates new behavior for any existing command within the scope of a Describe or Context block. The function allows you to specify a script block that will become the command's new behavior. @@ -128,7 +137,7 @@ Context "Get-Random is not random" { } } ``` -More information may be found here: https://github.com/pester/Pester/wiki/Mock +More information may be found on the [wiki](https://github.com/pester/Pester/wiki/Mock) ### Free Code in a Describe block Code execution in Pester can be very subtle and can cause issues when executing test code. The execution of code which lays outside of the usual code blocks may not happen as you expect. Consider the following: ``` @@ -138,14 +147,14 @@ Describe it { Write-Host -for DarkRed "Before BeforeAll" BeforeAll { write-host -for Blue "In Context BeforeAll" } Write-Host -for DarkRed "After BeforeAll" -  + Write-Host -for DarkRed "Before AfterAll" AfterAll { Write-Host -for Blue "In Context AfterAll" } Write-Host -for DarkRed "After AfterAll" -  + BeforeEach { Write-Host -for Blue "In BeforeEach" } AfterEach { Write-Host -for Blue "In AfterEach" } -  + Write-Host -for DarkRed "Before It" It "should not be a surprise" { 1 | should be 1 @@ -189,3 +198,4 @@ The DESCRIBE BeforeAll block is executed before any other code even though it wa Generally, you should have code reside in one of the code block elements of `[Before|After][All|Each]`, especially if those block rely on state set by free code elsewhere in the block. + diff --git a/docs/testing-guidelines/testing-guidelines.md b/docs/testing-guidelines/testing-guidelines.md old mode 100644 new mode 100755 index 85a9b17e6..0d431f921 --- a/docs/testing-guidelines/testing-guidelines.md +++ b/docs/testing-guidelines/testing-guidelines.md @@ -1,7 +1,135 @@ -author: Jim + +# Testing Guidelines + +Testing is a critical part of the PowerShell project. + +The PowerShell team created nearly 100,000 tests over the last 12 years which we run as part of the release process for PowerShell in Windows. +Having all of those tests available for the initial release of OPS was not feasible, and we have targeted those tests which +we believe will provide us the ability to catch regressions in the areas which have had the largest changes for OPS. It is our +intent to continue to release more and more of our tests until we have the coverage we need. + +For creating new tests, please review the +[documents](https://github.com/PowerShell/PowerShell/tree/master/docs/testing-guidelines) on how to +create tests for OpenPowerShell + +## CI System + +We use [AppVeyor](http://www.appveyor.com/) as a continuous integration (CI) system for Windows +and [Travis CI](http://www.travis-ci.com) for non-Windows platforms. + +### AppVeyor + +In the `README.md` at the top of the repo, you can see AppVeyor badge. +It indicates the last build status of `master` branch. +Hopefully, it's green: + +![AppVeyor-Badge-Green.png](Images/AppVeyor-Badge-Green.png) + +This badge is **clickable**; you can open corresponding build page with logs, artifacts and tests results. +From there you can easily navigate to the build history. + +### Travis CI + +Travis CI works similarly to AppVeyor. For Travis CI there will be multiple badges: +The badges indicate the last build status of `master` branch for different platforms. +Hopefully, each badge is green: + +![Travis-CI-Badge-Green.png](Images/Travis-CI-Badge-Green.png) + +This badge is **clickable**; you can open corresponding build page with logs, artifacts and tests results. +From there you can easily navigate to the build history. + +### Getting CI Results + +CI System builds (Appveyor and Travis CI) and runs tests on every pull request and provides quick feedback about it. + +![AppVeyor-Github](Images/AppVeyor-Github.png) + +These green check boxes and red crosses are **clickable** as well. +They will bring you to the corresponding page with details. + +## Test Frameworks +### Pester +Our script based test framework is [Pester](https://github.com/Pester/Pester). This is the framework which we are using internally +at Microsoft for new script based tests, and a large number of the tests which are part of the OPS project have been migrated from that test base. Pester tests can be used to test most of PowerShell behavior (even some API operations can +easily be tested in Pester) + +Substantial changes were required, to get Pester executing on Non-Windows systems. These changes are not yet in the +official Pester code base. Some features of Pester may not be available or may have incorrect behavior. Please make sure +to create issues in [PowerShell/PowerShell](https://github.com/PowerShell/PowerShell/issues) (not Pester) for anything that you find. + +### xUnit +For those tests which are not easily run via Pester, we have decided to use [xUnit](https://xunit.github.io/) as the test framework. +Currently, we have a minuscule number of tests which are run via xUnit, + +## Running Tests outside of CI +When working on new features or fixes, it is natural to want to run those tests locally before +making a PR. Two helper functions are part of the build.psm1 module to help with that: +* `Start-PSPester` will execute all Pester tests which are run by the CI system +* `Start-PSxUnit` will execute the available xUnit tests run by the CI system +Our CI system runs these as well; there should be no difference between running these on your dev system, versus in CI. + +When running tests in this way, be sure that you have started PowerShell with `-noprofile` as some tests will fail if the +environment is not the default or has any customization. + +for example, to run all the Pester tests for CI (assuming you are at the root the PowerShell repo): +``` +import-module ./build.psm1 +Start-PSPester +``` +if you wish to run specific tests, that is possible as well: +``` +Start-PSPester -Directory test/powershell/engine/Api +``` +or a specific Pester test file: +``` +Start-PSPester -Directory test/powershell/engine/Api -Test XmlAdapter.Tests.Api +``` + +### What happens after your PR? +When your PR has successfully passed the CI test gates, your changes will be used to create PowerShell binaries which can be run +in Microsoft's internal test frameworks. The tests that you created for your change and the library of historical tests will be +run to determine if any regressions are present. If these tests find regressions, you'll be notified that your PR is not ready, and provide +you enough information for you to investigate why the failure happened. -> Jason/Jim: Testing requirements (code coverage, required for incoming features/enhancements) - > local build/test execution instructions - > tools needed for build/test execution - > our CI explained + +## Test Layout +We have taken a functional approach to the layout of our Pester tests. You should place new tests in their appropriate +location. If you are making a fix to a cmdlet in a module, the test belongs in the module directory. +If you are unsure; you can make it part of your PR, or create an issue. The current layout of tests is: +* test/powershell/engine +* test/powershell/engine/Api +* test/powershell/engine/Basic +* test/powershell/engine/ETS +* test/powershell/engine/Help +* test/powershell/engine/Logging +* test/powershell/engine/Module +* test/powershell/engine/ParameterBinding +* test/powershell/engine/Runspace +* test/powershell/engine/Logging/MessageAnalyzer +* test/powershell/Host +* test/powershell/Host/ConsoleHost +* test/powershell/Host/TabCompletion +* test/powershell/Language +* test/powershell/Modules +* test/powershell/Provider +* test/powershell/Scripting +* test/powershell/Scripting/Debugging +* test/powershell/Scripting/NativeExecution +* test/powershell/SDK +* test/powershell/Security +* test/powershell/Language/Classes +* test/powershell/Language/Interop +* test/powershell/Language/Operators +* test/powershell/Language/Parser +* test/powershell/Language/Interop/DotNet +* test/powershell/Modules/Microsoft.PowerShell.Archive +* test/powershell/Modules/Microsoft.PowerShell.Core +* test/powershell/Modules/Microsoft.PowerShell.Diagnostics +* test/powershell/Modules/Microsoft.PowerShell.Management +* test/powershell/Modules/Microsoft.PowerShell.Security +* test/powershell/Modules/Microsoft.PowerShell.Utility +* test/powershell/Modules/Microsoft.PowerShell.Security +* test/powershell/Modules/PSReadLine + From 2920a3db665c6a5c09c4bd05d0c8ad1bfa20cd82 Mon Sep 17 00:00:00 2001 From: James Truher Date: Wed, 27 Jul 2016 18:43:03 -0700 Subject: [PATCH 03/25] Add images to this branch --- .../Images/AppVeyor-Badge-Green.png | Bin 0 -> 2334 bytes .../Images/AppVeyor-Github.png | Bin 0 -> 13910 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/testing-guidelines/Images/AppVeyor-Badge-Green.png create mode 100644 docs/testing-guidelines/Images/AppVeyor-Github.png diff --git a/docs/testing-guidelines/Images/AppVeyor-Badge-Green.png b/docs/testing-guidelines/Images/AppVeyor-Badge-Green.png new file mode 100644 index 0000000000000000000000000000000000000000..777ca2c4b443fa82f5739a17c50eee5e1cf4e82d GIT binary patch literal 2334 zcmb7G`9Bkm8=twBnJdN|IitvtqsftD#1y5R<)~O$D@RtyM9Nt#rE=t);X}#R&>T6! zmMgawmTOtDq*#Rc?(_W*K0iFq`}I7p*YmvIulMtMUeA+u+RX_frYHsg03b+bhckS9 zz&BG6knhbF{Xl#Wh&Bf4uGqQS0RSXCc>AI-Ki(7W>>CLHNWA~o1ZZKE z!Th8G*3k!hHtaGs>f#L)Ap9aa6l)NQ!m61X7#WzMl8jLR00@tCu=9ux;N*hO%6da- zf53E%5P=b_s@m4+nVO*XpgGyGyHdIj6Xzj3#l8f~XmrN`fLUtSys|yojdVM6K%|Go z9kmJy4=sQun#Y-aKS63U&UmmU=|^GgmfHwKZ`6a6lV8Of`-l5t*E%lcXna%t_!l); zeU{246^8owe}f7YGk3kdwQ|<=F&KYLW!5=aweU|0#nD} z@w7W{drG1%*P?o%8OI6FOGmzu$>b0kSf`xl$(=v>vEtu`6hznw1~u}EzrRWyN@PZv z^CX-gS@KSal9O-Je4tG=1-g@j3ic8Sd)p8N0c6X`|l;tuI@wHJsp(4-7wZ1rP2?97O@M{$5>MG1y5pwQ4rAyBgZJ znBg+PZx4lQ_r>>sI!HYRN}HtRBO7NaQj%W+6$5>x6lcGS7G`l*zmGJ;#O-){ft|Rv z^v}#)3F-G>CzZK{8GK6%Jk7A6+ z9A|Y?=9HJ2E%|W3GJ_N(dVokIHUlT1*~P#2TUF9wz;oerCPB}FZ2e`n!a%&;&^FS7t8FJJvYFAfcuu?R1@{70-8{{B99cr5Azl#M?_jH zo6vuBvUVaAhyHxuxAZPn3c4QW)2$A+;v8r%Cg8%UhVCEfENNiV!>`i9iH>C<`i(t5EqoqXvh|mrKG; zqjwX2v4;rFs#a=Z$pYI4B`80;4tbK?rPbTp)pf*;c4GrUjn62L5>2Wi%C);~b+v3I z6oO5@Ce7$;{K_kb8fC$uF7r6J{q*G`IpK67O|EDSQi}99@D81KNPWJ_6QDjTYw zg%m*0U}nd&FRT_qa$g_+oiCdTHIgTy$jZ0N%nPF!xZBCkc{k6Rse3vEcK zBXNkSOG*Rz{cH7His$6dk}^|+2O*jgb~=pu>VnYohts>0CFhzU2IObGi!nR4n&zes zSTukA)+M+rUnFbVq{ZodefQyBv-P*Wj~)z>a!Ii1vXi4Ghq!}AREDn1dz2#DVc>{l zOJ}}7NS2tN3eS2cqmZj z>5l59w7ohKs>j5uVK7)T+!l%46Q3@)+?mSzjURt?qOXQiN8mNybJ$%QFd|3!@jwgw zS*;R?QoUGSsSqKw(AKZl_p|t^AR180i=&w#qrmz(lX?GY(fuvr*CO}836YmJZBg~f zf4kl>^v;~`3x}9d{@!0->VKw*ykh-q;X2hqWTGE|L~j|td}=OK5Ih+Q-jSUf)X}oJ zn&&VT;$pu(>~Uh+NCu0P%{5{BTF$&)t3sq_Lhs>bSNeFec!yFuTJY~xyV-#IB8cBqHjYkS!N`CRe(M^&bE?Im&MpV9OE3SX> zxA#KqMqI|nzcT@2Mv9fKuCbl7GAVg^dCY9!1f(u8M_@&R!C+9vm+H>xAE4ailS)V! z92_hzPDm&&K8-r`^sdi-FS~~i-IImy>&AG(_{7vtn(1lo2Ztql^*CaJ z3ga23t6ldOm3)8P9dYCrIj^@SJnvjsSeToe3j^t#Dm>}zT#RWIQlDrkn{fq8!EUna7a0G2 O0U#aS9BS+@B>oS!xoHsq literal 0 HcmV?d00001 diff --git a/docs/testing-guidelines/Images/AppVeyor-Github.png b/docs/testing-guidelines/Images/AppVeyor-Github.png new file mode 100644 index 0000000000000000000000000000000000000000..e467d28accf4e66a6eab7abdc34d9075dee9b5fc GIT binary patch literal 13910 zcmdtIWmFtr+veMZ;FbgkjRs55KqJ8k1W1BIaEHbT5TtP@(6~DU5AGgZ8g~os?jGDu z<^P;#<~?iXJ@d|*^Xc?jRMXYfReSHMz3=<_-B+Nz>}MQI5=;;Xgd-s?rT_vxK?nXH zM1KNo6=+|P0B=Yzh0h|Ok|DAk;KNgs4>BJ>pz?66J17e98N*s!9R>p7w*UP@>bA-= z1a^Y$KC0O%S{d6pLT!ye)=;x=b}ZkF>?k=|AS~~U;Os^q(7SF4u@6d4ItM9pilpkP zTU#yDp89E%c%%Z?M)lNOv#cB2f%GlYc#4`F+Wktu`QE6k9bb&F`R4AM))#gS+P!6& zVJy@%DrnVu3MMYAi>V_d@&;*s0^39*NpXGB3ONWWxlfVGIWGJ*tA7VMc5)>60AaL?LwfR#07`(W+;Hn>4SZHc)W|28tewa{H-HV@IT=rCoyYH6C!EC9xyT9kw z79au|nn9lcnQw3`ZD|pTl@zoutFM<-*Vfh^wxj^h^AsP_=u+^jPV*qSHy3 zgO=MY@EEQ-gc*5tn{zvMHJEVxc$$#a$j^ko0Iuu6VGZpuAUvAC>ydUub8j*87{H^L zavxxPsFfvacH^DW@wg#+&3tfmn|66LY3>-KvWOX`_~lFGr9isXQ9Vc=n?M>&LP8Q3 z7dN(J_a=Ju8^gDV9Ov>s?ww|DKt>O@!!sw08hCcxGr(}D)C1abo;(Dam!F?u-GT9_rB%f z@#H8P>-3q|PvJJ-l^<5k5^tg_D=WXvk#c_%AHO?3eh|_He_}bgPB=Z>*E%<=ah%<> zs2m@Re{USk^}2;eTZen0n2+*Ei!}W9KCRg^Su^Ht)kp6B9&wpiQr0rlUBKsYgZCIu zN*obgRV!6zPOY6MwUOL?{~?X{0C!%!S zEVy?59840xJoRbm`xMe_7nHH)?wianZT(<_`cX1k&)Ir&R1CP-EVTryu?(TflPBXF zgD_aw*$lrl;X_ST_(M9*GW{2EDCN-+5;4%5X*p=m&J$kp4D44*a{bcZ-JWnm=oy~- zBRZY73Jh;q)pLrT9-*l#j>!?j^SP%UwGT0RXw>Jk=ifoi4r5!~63s3dQfMXL8wX>` zLPrv!K40#pa^77T%n>qd?XhY=%Pw1M>3YJn zTy%4+B^N!@@Jcq^F2rRCeIWzORD9M-^v2Mhi+I=)Ge^(BP=a~_yl(F zjHQcz$}g{>gD%dQr;*NP4n^&&e;LhHCcq7PV180LXN z``SAsV>gAuN_@swklXm1wHOSvXG1={*sVT^H3dD=TCebPm$X~lrh+}}u_Kub%wLiG zu9lr7vmm*tGRL&9uXd0zx}t1#w5gsB=dGni@GhK+dl_c`s^Y22Y@=UYA(ZzW-b;$# zctWwa@+j878FZi!EiZgtB)VfNSlZi!P75?B?<%KgdDeO{}gsy33#s3#6?1^i|)vzM7_ z`i{{~Du(@oBh8)B$g66_^MO_2xV+W;tH4@MsE}%UYTn+0Oz|0nyrh`VL3d1-o7=2E>QP1m~Zs`acVQ)u5ZLZBW zGdl4f!{JiK-htzCY!%~5m1RQOf|ix#L^h?#(Zu;f?qMtKr+gkv179>Vd}XiCp=p8(l6#`X{nW|sp;3RUtL`_bLt~XA?xONAdpq) zDxsfh1DlYL5D!mnRh1Y*I6}4un;d9CD?hUDhvA_i+`zVhfq`Hm*2$?UR~MJK`1p_Y zkTN7F2-L_yPzvc0B;w-Y`t7XOCqF@l{2)mOB8`0TdDS`dz(*F>eQ?^Fy3ktdzoU^(c{Cqa8FLAx@bDZEG_Lc?@qUq#rZf=17a3l^)19wZR zf2}*5!TpCQzwgB2%6279ya$7)Wyn3|w9VYnNdtQOr>dc)r1X?r_lY)^C?v_e0?Y-8 zvZWWYRq!W+C!!}PYdT>tnnf~7Vjl>|+7MXRo;@toWP1r)~6QN(2I5#Z;h?x+ZKYqI;b4Vb|W+)&JuS3NstWK_vvc48Ct?n zQB?&7iU&bZ4XI`0=H`Y#D3!cx2>3em*=BV$HGhJ>E0~(VV2T>B{VV>v3JS0PA{n>Rb4DUY9dRmTlV6XjTaqq zkYv|qEx>-t*-0)9o1c&B#3s^9s*~8`CK0}89(3$UjyFKwo-8Db=I(RzW^<0HyZpRl za=xkxQuVXCJ8TT+d2C3MSe#VoK62AVebACM^IjP+3>{#3EHFTAVR?d!1Uw!DFB6JN zONCY}EG(E=SQNhTrR0c3dBfrG)KrQwj4@OslxH#QY;06mFfxR-#C_d&kGXPDFi&|` z!6wf=9UZN4jLv)Vl6-0+&K8-#Gi^JXL+e^Qe_86*tt91?%hcGjBx?E#knE;;@hX&pY0TgWG)3&! zq?weABXQ~8=^ygPt4j*|Cg~--XY#V?c>P&NanhSrRhau)?N(qXu9dL!v}+Gl{M`Ei z>-2%kZr7@A-?mG2ocz|!&Gj_*jdwOVXo=pXZY_H}%zNVL3EmKk$V;LUPea43!ouLY zhrYhPv#ntU=Jb@46PrG54Grp)XMqH49cw3(lPc<|iqD|dB?9$MXgcCSJzlS8H?4pmIM99Ugkc7eO zHLJtWVHFd*kdT!kV|${DbN1sg@y3=4H6%M{*e%Vm$Qnvtnzmx5)N?tL*02g2e$MRG zE^>m2{P_0kCr*;rM{*u%$sUZc)NId4gptJ96C3UKR1_8Q%}{4TY;iA4YNMe2xlt&M2$EXlTc`VUtJ z$3r}&sduVaEh+u4@lt>A&*_9!PXr`p>J5@_-G$dMW`9|;s18)ALe4vieUdLc6UsA% zVxVBgyxcDXVf&!R=6#Y@S;ww*);&CJICgz1G#Om?280`v`O+^m6ld1K(UI;&AQ7uh z0Ks=9Z^V-q7*XC0jzx zDz0b!0*PyW@#=hWC4_jUS5n2yuAdGMwjLlskrUo{yyI6EGaLIEYgE3RsYn{is za11OEn)C^#DA$kI{<3pJLqng#DJ)N7QNJsQgV_@YR##U?Mk21*u_Hy~!5^qkmfMgq zNd`zb5tJ0FZ;y<}%DTIidrME~loE5<$qDg&^yc+B>$ultXLY$7nR9!t zJ6bx~xhqQuQH!&!8!Wm=s1QS{v(Hc)um<#e$zuFZR)mNM8=CXo@&q zC7oT2oBlLr`K%jj=_dBe-pBYOcDj}e8(Ku!Wgn8FUj@6tOd?d%VA)0Qx!*t&t9y%i zlEJw6k3?@T1p+VR%slu9>#d=bnHhB|>{SWc?;TzuzNVZmw-=UC{H^(f+MZHub55Hy(JHMuc&m(h9SlZYcAxaa6Nz~sH znP}K5a+zchp{Bfs3KXp4RaZyF4{3s{-j!Xyiu_F$T%#dExamWPCk-z&O8b*`4$JRz zW6VF1Ep)CK`cR4Re|@PIpUw8UbRUw&8lQp_k{dM?@2oBR#WRAJSqco2w8W+s7PNwtk?HOJc(1zFY!m|g z{QQ1!TP3}#MfV}Pp55|aJq%}*yD7LYhNq}N6~)7NEAFQKb&#yL>AymsiBU)H?CcB< z%3u<0Zf!;P8uF#+sH+)Njn1bM0;vTs4E;8fBG$e;6bBX;63pWfcyhX;=rUO-e=coOC9dU?1|YqNH7 zFz4gr)6~@Dc(iC~Zhm{SSGpq~w;N#;1lS)wQ zFU}D1StUe0-Fy;6xP6hPUi}LzKL>HaRw`1l^s-V=R+uiEfLm%gFTf z^w=2t`}ZtZq{9CsAwZTjYHDY1A3GH6#%F2f>EYoKR#{e7R$D7RXUNXW!ND;oLHh!b z(lON7V>?yqDi&wsicZg%YGi#^i#rsYf z=f-z)Hal8dK>|$yI@f0&NDntS*baBg}66ns<# z_`}14665*rw%uJuBYS&$iE#n7`fG`e?9ICKiNMnLMR()Nr>(C_Ac8#S8`rwJyi8)N z?Qv#i$wWKWJ8W;WSN_NebuwOge3aJM>V`1gf8jCOPet$e=x0dhaBWC2(Labv%VgwoJ*D^NGhxe|ZcGvLeVdj|Rdz-6ACXUVBG=yzlv_AD~RR zm)xSI--95vPXDZr76 zJFVOQH+WSoZkR@cwK7oM%7TZoD@jsqII5nBLv515;HiL1LSL6irZ1nK-2{wqG&anP zCAij`O?G@gwYCA;fo#Dk#i$>*!XAQ6|2F2qenYzQO!#`BkL>%n~rBBACd|o_IaNNt@kmSjd-N^FNbmiA;OGUz2b} z!tHvd^rLPkIjXBKrV?(Vs;Tyr*&P+w^&|56%Q1sjtz}iv)98caV~!OgVq#L?Du=OR z!`AH9i=41D=&4HE&n!}6jt&*)30>`kJDm$A3F=B6;&>GM8|yKVYi@I zM0BcHb=CnXU-YXgoJw;%x!AY@WExay z*rJ~uqalrndYqd~KbBOFCKVe^-_SU_R)rD1WOQA2_O37(*$_I6Q;!QjvmL=2y~RA3 znwUokW`sa%>#h`x$&7<^z!rI|N%O(25q=yd(nmBfi-0K}PoH4YT`est0V0?R@T5jg zl1R$-lIq*|*k@*{{$ZT!Uy?!af;$=c3`k*Qp5|5%vzBshsGcDkCkKE@B884jB6QhnMrbY+|t@g4F#&o)>MXU zfLUqX@dlGZqVZ8Hx=$wgKXuJm$O=JXf;iY@yp4sGy{Cq_a;@SZNx-!3j=xtQi=t%BuB7;Kg6Gf0Hz z3%zAIV8V^bJ;jyqkog78$g$S4d2sNpoVE#BJYtgnTz)oaYmg^y2W2MU^*C5|&?xRa zNKZ=7Zj3BGMX8aStN^mv5<=#V_jYLUD`oEEG;MEP&}@%&a)U5=CPC?^D={0a4j1|( z&{ZJ<=w|yo?=%kce))$m5BlVI(P+aIkb?ivI9F+*nbG;TxqZKRp^5@wJw^%F6#G(> z`d=R5xy@T4A-ok4VPnhOMZ5-GnyO9wV;YUAgRcEi97r%|Yq8NoeGT`fM^UrQ)2~U` z4C2HD+Q)}pL6y(VgG>%7G$PqW%;NMqJ-SpZoNF#7L`?+a2xMpu5BTI1B_ux%Nf4QS zAaT8j$jHg^N7m2pN?%t}&t1!WCL+51{?j~W@?MC|k{XFDW;lH&?i_>js~3l&W!0u$c#T<(9h9=cJ963mys-0CU=!H)JW}J|k8b_VJ7JwysNTn$9ioHjK z@BIz;PAQq%;^?;?7a1v7=0fsF)S>*EAI5E6?W-dawuJ6%Z%{)%2VJ-ze>yeVVn~*) zOxfAlA6P?8RG8W(97g4HcERdz$!T#==zkHZsIW+@UxxktwSENmz-tqh&-%Tbnh>b} zCprPw9_t)=)r$Np>#PgJXE!7XjxD(W++_N*&=VGgqpy?F& z%3{6TAXntB+FNS_LnV2-z0b6c>b$76EmeBt7JQ!6fh;E7>=iYehG^Qo$2TmQ{JN;Uo<#3&?q@U=xb|+x%~dmE@@ozQ zP9}!!uRFL!+l5lpOu|}tVbA9#F8mb_$=re3J(0dd+ zUe6`G@0~bwD(_f-(PdNr3(!XwBkA4$?aq~R_Onkywj{Y-%6~$?Y2PYXn@0m zPMy97KFk$SV*97Km25Wjd;xG{7^+3m9u2Q0Y+&!!iVFL)m!R&T+80*w(RWJFHpbRi5PEt zK|r8IVoGcm2L}gnY-3|%okpkf=H|um@yf!>N z(5q}89_EaAk4ez^{`-(Txc9fmg_<8feypvn5wKZUT1IjK3j!-MvpgS$&m;w)hMY|3 z0RqXgXep%+=w5by{sy4f>hYC2QCfj-$9Ga^Yg=)1iYDG~KzAjk7NcEK4)VL<6Mt_& zi;mmir3N$EAJyj%@}KpCv&jT@QstHNKHq1iIVISSNlJ+rn~h9ZJMqjnA?vjOm~-UD z5q7)Y8{OR8ys@z%{f2{!YjSMt^y!K~#`gG{;xcJ8d+HPgZ zQWF!s!{O^!#z^tMYHP^d+PbWzMc3Tw+d)|B{ZQOS1BU_O>s_L{26P`{I$Dhagd#J1 z!QX$wYEbPG@1<3D9nmjLC}{au;WuKrYkq#dwbe@=WmaMPS#YPRr=?}+6LiUp6hI`K z4VLrYOm9R*_17)A=<8M%-7WqQ1t;UPJCe^PMJ07J*{LI07R-9-1kO%*Hi%@3T$Fa%Q7tWd$ z$OK&K2pkfy*)O9%fwKAB+4oNjU6qY9>5a^O^O~w$l~vhA@v?TKjufl%t}ex1m&o<` zSa@b1W!~}DnHVf7Ctp6_V%lAuV>YU;M5x*eD#@Bnbx*F@vp3v*-4gK7eoFQPkm~fz z5OrN$q86e0^73*(&erYNCB2Y9efjdGi;IgmojB=J0%7^Sjt*bu0ULBt_>IwR`-OpJ z2ZZqD+39A;3xl^WaUqXlEJd)k9o(5BnLHYX7#d19qBC>l^*V)8PnVQTch7`kn{{Sq z{j%u!m%p%mbDi|*)K87=<1YM?!@jhV<9 z7qzciUNP!oxtCO65gJ915USy_ns7e$->GTvk-DmfB%JkzahIaJrmH0Wn(@{w9K+{G zpFF>{Q1v9DwDIuyxX=EvvhK$%My98&-cO*@)JLpZk3Bu&s;WfS_p!0DTf=FJYQp@$ zjEQLgN*#PuFBtR#y4Q+}iz@_jDG}-F&WjRN5&j0aySWw>K7&?ea5SuZ+0Ch1v{gcD z$DaEn-W@U9_CJ2=n@?~hu_JDct(7984#meP7}v2Oh0r2E`Q&C zBspuNj{by@C!Wo2xbj}_i`$ZWGh3i9s?XKu(y9=f3idIE<4DOSZGgVIW*=`iR8$;I zm$gt6dD@38-3|Nq!@&?0EA2n-qt_u=qRvjKxnHQ3I!7+U73R=iwnBk*0y<7f5*l?$ z*CHnim?I*==s4*hV1h5!+ZX2N2XgvYeBw2H6)5&?v5}!4z~b`h`Lu_H*ZRn90*XW0 z7}zF5(1(yZmNie7*#9RytwUvAPtL`6$FYMA9}eAn@7~0HUHJv8TW^z@x!JLIDfp=} zK!9S-pK>Pj7e9tpPQ1|=#RV8QX4VsTr`H>J0>_|nqP)TH(9wi;cyR8*ZK zW!|K)mSX=Oqf@cq>nu7)s172%>DnlDz^1*QnOuq>2#xbDds4xy=N(IW$(*ZcX0i82 zT<+dcO2$Bk9+X@tcYg zNdEj)GVw60o;!`$miI|Ov&dk-00^oIGEc#7QD#^RnIPBojs~GNDNm_w|JsnfO_T zdhdCE1XtWEHwS4laE1P1pn-!FQGdP4i+gT6482q#IC`z=>* z`~B@D-J3V`@?c`(>lOc3K(yQ4+cR?SnhQS>un~> z&|ij1T6&u)Ef8mS^0nn{2xyt|Z`^A`vgGIEqt{Pwc&M&^H-`Kj@m-1WV<0VZXlQ5_ z8tn_atK*e+CjnW^(UB4BvrU;wR3hjxweIbm{QUhFBg^#JgZwFOxC~Vt8mFuND;Jd3 zjGq8ueikT}lbZ_weFm+Bv^2Rl(K~i7Mn-UluI_G4O--OWN+IAR3{+%=Gmu|%adZFr z^$VcP=%N|wI~arrHJ?f_UbE`l$dnB@{>``VHB$(4wQG@9*zv zL0DK=Sx;$^0fyROv(|Mm_Y0^R0#xm2v1x8{^5T3-cRYi6*c(FdV)Bu30d08EH&#vU z|2GiTuu^>tfVgN+@)0*T_5YthR7(B-J^1?nj%lrF;ZSpXXYIqkBopGV3)V5Az{Q(y zXsKlg|7Fb2lCq~2`5Cw%<^UCuU&^hr>ig?+-R7J2^UB>u%F0S=Tp$5Axqh;?@8T09lc%P7x6+DgTnk>|(TNuD z3pk(+gbPNNmeM4%Q~A`iwX=%=T5gtvCdDn3-}qbLS2N$qgnz6ji5A6G`~U5U+ha0; zi@Qy;zYRU3RjFn@dTl>6={*{`5m&wueh`H$PfEx|{C91vUj97pI&N zm&aQlxd5lb-x2zsIoaTZsMO>v)mg>{)muZ2-Px+C}H&t!uj zqQ%^VyspXQsYL;S`&#Ay;+T~J%6O{qmbx?D9oAeNX+pKWrFn1QS{MHRf$eGH`=!`1 zTYnP6etuee(kk%{nz1fYnrtX3fl@B7FxlJKn7z1fjZ%tGf~O>im+5VqImP0mX5g6f zD*sLQFGBT+P;n5d{mUzcltV?m-D!IMwowc!ZBN&wDZ8w$)-n{COV`=)iABLK+33m4 zdz?=~oxCP&0A%KiF{7iim8fA(so(yBGtW~V1=QM%1nsf8ThFibUW{pMc-5>YORbF# zcQxp(I+*mJO9}b-l~tF=HEQ@}@3!cqrUJF3Cjr+&Gn<@|e>dHsX%%3x0Zq$6Vrj!u z_G#ORhQ!lYc^5FTu7g{ zVb3e5qJ;8sf0zLYaGo;!FZo4FOyHC7BEhm?NKax`l)`n@Xqc8b&+~xCm@sszXN7|V zY61RQgwSW_Z_J0wd^oBl91OR6;W}K;W3ux^4PDUT^|Nk`n(D!Re{U!JKZga)IV@F= z<{L*x>Me>BH0G@PBy3sOo>ty=-_;P>F~Px>)pPD9r2+R;y)X)c~dH!Y^< zP`H54B;pvu(`F8Cxg97%9@{X(A!(zZsO6Q2=wEw)BG-%s7fC4Yt7m|~+}peM zI0hE7#TUT-EX*t%p@*xry{S^Hir0>;g^Q$FIJSUI2$vZ6cD=hd!&S6zbZUy5lM|?+ zRyQ@hRn+cL1)o-DgIoOH(T=T{X3I zyBDa%g1$(g<01J*1f^EvTwI5qp`jt5wB6mc?|uVTf-Ji+jN+!D(Ol})+z(QVOtC^3 zN$oOV6_@WBIv4#ZfbdQARJ>Hl{5h-Ji9U%}Wc|~JZUMgl^PFJaKX(o4VXK0$Ni;EG z9W3cYe0Z<(R~t*cNg^m)12r}PaoqI2q0aquT|!rP>Gah0O*Annskxb%^W7C&wiV3O zzigJD>|VBLwWBu(`fw|7GCQ_blXmC$+%H9~NeJO__?BOue4mQA=aYG%ND6~Oz*PQ_ zymGq12QUQ$>#}m!%KRZcWk^&ybXXRCuU!4*+Gh?GxTP1uz`!3L)x1S{s?Y!K zU9325>U(#|t@k`U(@RUG)!e@vKBpZBI2LhQ@TIGL>}5E)O?^QGg{=9CNhv!?W+htZ zcC`m0Z;fF3RC8$${&PaWvPBBmwSY3K2%)J|hA8vPpZ7o(g-J;dcL36w?04OV+XnGc zk}O*uIVJ=RW*BS)un0 zA9jBnLkZ;H%6L8azboUsv(lT??cL!O7HpO#%blz)jDF`0HPXDAPuL| z0MT6QQ9td_qjTo|MvN|Z(ji;1KDf(#fWv#AYc5B2u365M`K8$0ihL`(;-x_f&0WS2 z%IA_2)IxUoo}A|b!R!$2t5w%s!gGk*sOp!?fRv-@b9P-Lp#wJPv33y+q0>1d#cAx6 zpuS54dGl`Jww4hb#DggeuIahOni67XADfu?=;3K(v~hj5MeuTD=<14RgXQhpNZA0f zAn@vmleu{z^DsjIghw@%P^BjlMdQU+mxAazy~8{w6t{}N2B9;qVc^HEim_yhE#S&wGIIP|Mr2YRt&qOX;30qfR%|qFwV>RmK~wL$Ei~F4r27oL=>4- zX{77tQD0xPL5kZ)mWN$%%XJ!FJQkZ?(PI7fZRQyBaDfZR`!=HQH@SJ^dy6^I5{ zL)vpb{BIe7mK7ziLz$HB7-6mh?Zl6;e8W`>?-ztpKUn||%`^TAEFb;!gFp?q*pKZo zv;$}Ll~`hPj)A2)8iII|JTj@*@7R^4;Y#WI4WG4$47ZQR*X?z`eGkNV5{wb@n5;V7 zwads_(VKO)5esFTdfNIW9q=a@82HpIEGz_ytpYh4HJnm8z06DOyWujBt`o3CXbb@6 ziGcxub$J&}%^&K>mIq-EGB4ALnTEM8S$lAmw!XEzF1g$ZyVXCZ(8}bIZ2$b%ex)X7 z`=Go$i~so^b5<<=ec7xn^75PL1`MAPR7UWA$hohUo%aoXv)aYN`n2+M9*7nVYIoLX zp-DJG_bQmz1!Gc(uQqd(s^j|t0TVu-$pR@c%ZBO!UA>qn)4j!7d< z`&XlU@KN{q1nyx{PUdm;E+srVv6-k|eC8<<%d5=xQ|vhLg5sf;F|F3IJNZn=Y2@`TGlfh92{<|MNV_;=cufw)x&t5YpkxW&duEd_yR2us|onz^?_B|)wSWT7$mb%aS<6o z0nq|h$zdFEFyNbEPsHA7TVFTy^c2EqMIfFqAoaF3xn6#oueG_oH~`S};^HD;Qmd)1 zcE3NLvZL>ZQDT1vb7?8p<1Hb{X8~5zqT*tVv_-%R0jwt^^18a72ea=op3;J`pl`n~i%zgkq24mwK-as*Z2ZuNX-w%8#T>U|o&0(qE@&1kI|Du{%;l(>)N@X=& z-FR&zkeBGENX)+$8t#AcBZB|>_JZ+mLKXDgWcWddDI{Xx&jr)p9UzI1vSKA7df)#q D<@!M> literal 0 HcmV?d00001 From 8d758b63f2f69a292dde16db0b8176361bb393d7 Mon Sep 17 00:00:00 2001 From: James Truher Date: Tue, 2 Aug 2016 11:50:52 -0700 Subject: [PATCH 04/25] updates based on PR feedback --- docs/testing-guidelines/PesterDoAndDont.md | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/testing-guidelines/PesterDoAndDont.md b/docs/testing-guidelines/PesterDoAndDont.md index 250e5b6f0..1dd7c91c2 100755 --- a/docs/testing-guidelines/PesterDoAndDont.md +++ b/docs/testing-guidelines/PesterDoAndDont.md @@ -4,7 +4,7 @@ 1. Test only what you need 2. Reduce dependencies 3. Be sure to tag your `Describe` blocks based on their purpose - 1. Tag `CI` indicates that it will be run as part of the continuous integration process. These should be unit test like, and fast. + 1. Tag `CI` indicates that it will be run as part of the continuous integration process. These should be unit test like, and generally take less than a second. 2. Tag `Feature` indicates a higher level feature test (we will run these on a regular basis), for example, tests which go to remote resources, or test broader functionality 3. Tag `Scenario` indicates tests of integration with other features (these will be run on a less regular basis and test even broader functionality than feature tests. 4. Make sure that `Describe`/`Context`/`It` descriptions are useful @@ -12,14 +12,22 @@ 5. Use `Context` to group tests 1. Multiple `Context` blocks can help you group your test suite into logical sections 6. Use `BeforeAll`/`AfterAll`/`BeforeEach`/`AfterEach` instead of custom initiators -7. Use Try-Catch for expected errors and check $_.fullyQualifiedErrorId (don't use `should throw`) +7. Prefer Try-Catch for expected errors and check $_.fullyQualifiedErrorId (don't use `should throw`) 8. Use `-testcases` when iterating over multiple `It` blocks 9. Use code coverage functionality where appropriate 10. Use `Mock` functionality when you don't have your entire environment 11. Avoid free code in a `Describe` block - 1. Use `[Before|After][Each|All]` _see Free Code in a Describe block_ - + 1. Use `[Before|After][Each|All]` see [Free Code in a Describe block](WritingPesterTests.md#free-code-in-a-describe-block) +12. Avoid creating or using test files outside of TESTDRIVE: + 1. TESTDRIVE: has automatic clean-up +13. Keep in mind that we are creating cross platform tests + 1. Avoid using the registry + 2. Avoid using COM +14. Avoid being too specific about the _count_ of a resource as these can change platform to platform + 1. ex: checking for the count of loaded format files, check rather for format data for a specific type ## Don't -1. Have too many evaluations in a single It block +1. Don't have too many evaluations in a single It block 1. The first `Should` failure will stop that block -2. `Should` be used in an `It` Block +2. Don't use `Should` outside of an `It` Block +3. Don't use the word "Error" or "Fail" to test a positive case + 1. ex: "Get-Childitem TESTDRIVE: shouldn't fail", rather "Get-ChildItem should be able to retrieve file listing from TESTDRIVE" From 935185cf6b6c91e688de03dbedee73978ae9a279 Mon Sep 17 00:00:00 2001 From: "James Truher [MSFT]" Date: Tue, 2 Aug 2016 11:55:50 -0700 Subject: [PATCH 05/25] fix don't section so it's visible --- docs/testing-guidelines/PesterDoAndDont.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/testing-guidelines/PesterDoAndDont.md b/docs/testing-guidelines/PesterDoAndDont.md index 1dd7c91c2..da4dbae4c 100755 --- a/docs/testing-guidelines/PesterDoAndDont.md +++ b/docs/testing-guidelines/PesterDoAndDont.md @@ -25,6 +25,7 @@ 2. Avoid using COM 14. Avoid being too specific about the _count_ of a resource as these can change platform to platform 1. ex: checking for the count of loaded format files, check rather for format data for a specific type + ## Don't 1. Don't have too many evaluations in a single It block 1. The first `Should` failure will stop that block From 28a06155c8989d88f022c8876b0a76873135b194 Mon Sep 17 00:00:00 2001 From: PowerShell Team Date: Wed, 20 Jul 2016 14:05:54 -0700 Subject: [PATCH 06/25] add map.json file for migration of Pester cmdlet tests --- test/powershell/Modules/map.json | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 test/powershell/Modules/map.json diff --git a/test/powershell/Modules/map.json b/test/powershell/Modules/map.json new file mode 100644 index 000000000..2d6368100 --- /dev/null +++ b/test/powershell/Modules/map.json @@ -0,0 +1,23 @@ +{ + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/FormatHex.Tests.ps1": "Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/ImportExportCSV.Delimiter.Tests.ps1": "Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/MiscCmdletUpdates.Tests.ps1": "Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/NewGuid.Tests.ps1": "Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/NewTemporaryFile.Tests.ps1": "Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.ArchiveTests.ps1": "Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.ArchiveTests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.GetCommand.ps1": "Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.JsonTests.ps1": "Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.JsonTests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1": "Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.core.job.tests.ps1": "Modules/Microsoft.PowerShell.Core/core.job.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.History.Tests.ps1": "Modules/Microsoft.PowerShell.Core/History.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Management.Copy.Item.Tests.ps1": "Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.alias.tests.ps1": "Modules/Microsoft.PowerShell.Utility/alias.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.clixml.tests.ps1": "Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.command.tests.ps1": "Modules/Microsoft.PowerShell.Utility/command.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.formatdata.tests.ps1": "Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.object.tests.ps1": "Modules/Microsoft.PowerShell.Utility/object.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Utility.PowerShellData.tests.ps1": "Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.string.tests.ps1": "Modules/Microsoft.PowerShell.Utility/string.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.typedata.tests.ps1": "Modules/Microsoft.PowerShell.Utility/typedata.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.xml.tests.ps1": "Modules/Microsoft.PowerShell.Utility/xml.tests.ps1", +} From 721ad34c62446d931543fb49377af69fb6efa0c6 Mon Sep 17 00:00:00 2001 From: PowerShell Team Date: Wed, 20 Jul 2016 14:27:27 -0700 Subject: [PATCH 07/25] add missing sample archive file --- test/powershell/Modules/map.json | 43 ++++++++++++++++---------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/test/powershell/Modules/map.json b/test/powershell/Modules/map.json index 2d6368100..2c5b58594 100644 --- a/test/powershell/Modules/map.json +++ b/test/powershell/Modules/map.json @@ -1,23 +1,24 @@ { - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/FormatHex.Tests.ps1": "Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/ImportExportCSV.Delimiter.Tests.ps1": "Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/MiscCmdletUpdates.Tests.ps1": "Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/NewGuid.Tests.ps1": "Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/NewTemporaryFile.Tests.ps1": "Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.ArchiveTests.ps1": "Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.ArchiveTests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.GetCommand.ps1": "Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.JsonTests.ps1": "Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.JsonTests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1": "Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.core.job.tests.ps1": "Modules/Microsoft.PowerShell.Core/core.job.tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.History.Tests.ps1": "Modules/Microsoft.PowerShell.Core/History.Tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Management.Copy.Item.Tests.ps1": "Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.alias.tests.ps1": "Modules/Microsoft.PowerShell.Utility/alias.tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.clixml.tests.ps1": "Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.command.tests.ps1": "Modules/Microsoft.PowerShell.Utility/command.tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.formatdata.tests.ps1": "Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.object.tests.ps1": "Modules/Microsoft.PowerShell.Utility/object.tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Utility.PowerShellData.tests.ps1": "Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.string.tests.ps1": "Modules/Microsoft.PowerShell.Utility/string.tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.typedata.tests.ps1": "Modules/Microsoft.PowerShell.Utility/typedata.tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.xml.tests.ps1": "Modules/Microsoft.PowerShell.Utility/xml.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/FormatHex.Tests.ps1": "Microsoft.PowerShell.Utility/FormatHex.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/ImportExportCSV.Delimiter.Tests.ps1": "Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/MiscCmdletUpdates.Tests.ps1": "Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/NewGuid.Tests.ps1": "Microsoft.PowerShell.Utility/NewGuid.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/NewTemporaryFile.Tests.ps1": "Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.ArchiveTests.ps1": "Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.ArchiveTests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/SamplePreCreatedArchive.archive": "Microsoft.PowerShell.Archive/SamplePreCreatedArchive.archive", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.GetCommand.ps1": "Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.JsonTests.ps1": "Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.JsonTests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1": "Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.core.job.tests.ps1": "Microsoft.PowerShell.Core/core.job.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.History.Tests.ps1": "Microsoft.PowerShell.Core/History.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Management.Copy.Item.Tests.ps1": "Microsoft.PowerShell.Management/Copy.Item.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.alias.tests.ps1": "Microsoft.PowerShell.Utility/alias.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.clixml.tests.ps1": "Microsoft.PowerShell.Utility/clixml.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.command.tests.ps1": "Microsoft.PowerShell.Utility/command.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.formatdata.tests.ps1": "Microsoft.PowerShell.Utility/formatdata.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.object.tests.ps1": "Microsoft.PowerShell.Utility/object.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Utility.PowerShellData.tests.ps1": "Microsoft.PowerShell.Utility/PowerShellData.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.string.tests.ps1": "Microsoft.PowerShell.Utility/string.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.typedata.tests.ps1": "Microsoft.PowerShell.Utility/typedata.tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.xml.tests.ps1": "Microsoft.PowerShell.Utility/xml.tests.ps1", } From 7305b82b73df5af7eb9b50fbdfc8ce7e29615cd9 Mon Sep 17 00:00:00 2001 From: PowerShell Team Date: Wed, 20 Jul 2016 14:28:19 -0700 Subject: [PATCH 08/25] Add migrated files --- .../Pester.Commands.Cmdlets.ArchiveTests.ps1 | 951 +++++++++++ .../SamplePreCreatedArchive.archive | Bin 0 -> 270 bytes .../History.Tests.ps1 | 64 + .../Pester.Commands.Cmdlets.GetCommand.ps1 | 49 + .../core.job.tests.ps1 | 42 + .../Copy.Item.Tests.ps1 | 867 ++++++++++ ...mands.Cmdlets.NoNewlineParameter.Tests.ps1 | 26 + .../FormatHex.Tests.ps1 | 218 +++ .../ImportExportCSV.Delimiter.Tests.ps1 | 65 + .../MiscCmdletUpdates.Tests.ps1 | 54 + .../NewGuid.Tests.ps1 | 19 + .../NewTemporaryFile.Tests.ps1 | 38 + .../Pester.Commands.Cmdlets.JsonTests.ps1 | 1465 +++++++++++++++++ .../PowerShellData.tests.ps1 | 86 + .../alias.tests.ps1 | 160 ++ .../clixml.tests.ps1 | 187 +++ .../command.tests.ps1 | 80 + .../formatdata.tests.ps1 | 64 + .../object.tests.ps1 | 100 ++ .../string.tests.ps1 | 61 + .../typedata.tests.ps1 | Bin 0 -> 10702 bytes .../xml.tests.ps1 | 62 + 22 files changed, 4658 insertions(+) create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.ArchiveTests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Archive/SamplePreCreatedArchive.archive create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Core/core.job.tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.JsonTests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Utility/alias.tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Utility/object.tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Utility/typedata.tests.ps1 create mode 100644 test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 diff --git a/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.ArchiveTests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.ArchiveTests.ps1 new file mode 100644 index 000000000..387b0eb32 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.ArchiveTests.ps1 @@ -0,0 +1,951 @@ +<############################################################################################ + # File: Pester.Commands.Cmdlets.ArchiveTests.ps1 + # Commands.Cmdlets.ArchiveTests suite contains Tests that are + # used for validating Microsoft.PowerShell.Archive module. + ############################################################################################> +$script:TestSourceRoot = $PSScriptRoot +Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { + + BeforeAll { + + New-Item $TestDrive\SourceDir -Type Directory | Out-Null + New-Item $TestDrive\SourceDir\ChildDir-1 -Type Directory | Out-Null + New-Item $TestDrive\SourceDir\ChildDir-2 -Type Directory | Out-Null + New-Item $TestDrive\SourceDir\ChildEmptyDir -Type Directory | Out-Null + + $content = "Some Data" + $content | Out-File -FilePath $TestDrive\SourceDir\Sample-1.txt + $content | Out-File -FilePath $TestDrive\SourceDir\Sample-2.txt + $content | Out-File -FilePath $TestDrive\SourceDir\ChildDir-1\Sample-3.txt + $content | Out-File -FilePath $TestDrive\SourceDir\ChildDir-1\Sample-4.txt + $content | Out-File -FilePath $TestDrive\SourceDir\ChildDir-2\Sample-5.txt + $content | Out-File -FilePath $TestDrive\SourceDir\ChildDir-2\Sample-6.txt + + "Some Text" > $TestDrive\Sample.unzip + "Some Text" > $TestDrive\Sample.cab + + $preCreatedArchivePath = Join-Path $script:TestSourceRoot "SamplePreCreatedArchive.archive" + Copy-Item $preCreatedArchivePath $TestDrive\SamplePreCreatedArchive.zip -Force + } + + function Add-CompressionAssemblies { + Add-Type -AssemblyName System.IO.Compression + if ($psedition -eq "Core") + { + Add-Type -AssemblyName System.IO.Compression.ZipFile + } + else + { + Add-Type -AssemblyName System.IO.Compression.FileSystem + } + } + + function CompressArchivePathParameterSetValidator { + param + ( + [string[]] $path, + [string] $destinationPath, + [string] $compressionLevel = "Optimal" + ) + + try + { + Compress-Archive -Path $path -DestinationPath $destinationPath -CompressionLevel $compressionLevel + trow "ValidateNotNullOrEmpty attribute is missing on one of parameters belonging to Path parameterset." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "ParameterArgumentValidationError,Compress-Archive" + } + } + + function CompressArchiveLiteralPathParameterSetValidator { + param + ( + [string[]] $literalPath, + [string] $destinationPath, + [string] $compressionLevel = "Optimal" + ) + + try + { + Compress-Archive -LiteralPath $literalPath -DestinationPath $destinationPath -CompressionLevel $compressionLevel + throw "ValidateNotNullOrEmpty attribute is missing on one of parameters belonging to LiteralPath parameterset." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "ParameterArgumentValidationError,Compress-Archive" + } + } + + + function CompressArchiveInValidPathValidator { + param + ( + [string[]] $path, + [string] $destinationPath, + [string] $invalidPath, + [string] $expectedFullyQualifiedErrorId + ) + + try + { + Compress-Archive -Path $path -DestinationPath $destinationPath + throw "Failed to validate that an invalid Path $invalidPath was supplied as input to Compress-Archive cmdlet." + } + catch + { + $_.FullyQualifiedErrorId | Should Be $expectedFullyQualifiedErrorId + } + } + + function CompressArchiveInValidArchiveFileExtensionValidator { + param + ( + [string[]] $path, + [string] $destinationPath, + [string] $invalidArchiveFileExtension + ) + + try + { + Compress-Archive -Path $path -DestinationPath $destinationPath + throw "Failed to validate that an invalid archive file format $invalidArchiveFileExtension was supplied as input to Compress-Archive cmdlet." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "NotSupportedArchiveFileExtension,Compress-Archive" + } + } + + function Validate-ArchiveEntryCount { + param + ( + [string] $path, + [int] $expectedEntryCount + ) + + Add-CompressionAssemblies + try + { + $archiveFileStreamArgs = @($path, [System.IO.FileMode]::Open) + $archiveFileStream = New-Object -TypeName System.IO.FileStream -ArgumentList $archiveFileStreamArgs + + $zipArchiveArgs = @($archiveFileStream, [System.IO.Compression.ZipArchiveMode]::Read, $false) + $zipArchive = New-Object -TypeName System.IO.Compression.ZipArchive -ArgumentList $zipArchiveArgs + + $actualEntryCount = $zipArchive.Entries.Count + $actualEntryCount | Should Be $expectedEntryCount + } + finally + { + if ($null -ne $zipArchive) { $zipArchive.Dispose()} + if ($null -ne $archiveFileStream) { $archiveFileStream.Dispose() } + } + } + + function ArchiveFileEntryContentValidator { + param + ( + [string] $path, + [string] $entryFileName, + [string] $expectedEntryFileContent + ) + + Add-CompressionAssemblies + try + { + $destFile = "$TestDrive\ExpandedFile"+([System.Guid]::NewGuid().ToString())+".txt" + + $archiveFileStreamArgs = @($path, [System.IO.FileMode]::Open) + $archiveFileStream = New-Object -TypeName System.IO.FileStream -ArgumentList $archiveFileStreamArgs + + $zipArchiveArgs = @($archiveFileStream, [System.IO.Compression.ZipArchiveMode]::Read, $false) + $zipArchive = New-Object -TypeName System.IO.Compression.ZipArchive -ArgumentList $zipArchiveArgs + + $entryToBeUpdated = $zipArchive.Entries | ? {$_.FullName -eq $entryFileName} + + if($entryToBeUpdated -ne $null) + { + $srcStream = $entryToBeUpdated.Open() + $destStream = New-Object "System.IO.FileStream" -ArgumentList( $destFile, [System.IO.FileMode]::Create ) + $srcStream.CopyTo( $destStream ) + $destStream.Dispose() + $srcStream.Dispose() + Get-Content $destFile | Should Be $expectedEntryFileContent + } + else + { + throw "Failed to find the file $entryFileName in the archive file $path" + } + } + finally + { + if ($zipArchive) + { + $zipArchive.Dispose() + } + if ($archiveFileStream) + { + $archiveFileStream.Dispose() + } + } + } + + function ExpandArchiveInvalidParameterValidator { + param + ( + [boolean] $isLiteralPathParameterSet, + [string[]] $path, + [string] $destinationPath, + [string] $expectedFullyQualifiedErrorId + ) + + try + { + if($isLiteralPathParameterSet) + { + Expand-Archive -LiteralPath $literalPath -DestinationPath $destinationPath + } + else + { + Expand-Archive -Path $path -DestinationPath $destinationPath + } + + throw "Expand-Archive did NOT throw expected error" + } + catch + { + $_.FullyQualifiedErrorId | Should Be $expectedFullyQualifiedErrorId + } + } + + Context "Compress-Archive - Parameter validation test cases" { + + It "Validate errors from Compress-Archive with NULL & EMPTY values for Path, LiteralPath, DestinationPath, CompressionLevel parameters" { + $sourcePath = "$TestDrive\SourceDir" + $destinationPath = "$TestDrive\SampleSingleFile.zip" + + CompressArchivePathParameterSetValidator $null $destinationPath + CompressArchivePathParameterSetValidator $sourcePath $null + CompressArchivePathParameterSetValidator $null $null + + CompressArchivePathParameterSetValidator "" $destinationPath + CompressArchivePathParameterSetValidator $sourcePath "" + CompressArchivePathParameterSetValidator "" "" + + CompressArchivePathParameterSetValidator $null $null "NoCompression" + + CompressArchiveLiteralPathParameterSetValidator $null $destinationPath + CompressArchiveLiteralPathParameterSetValidator $sourcePath $null + CompressArchiveLiteralPathParameterSetValidator $null $null + + CompressArchiveLiteralPathParameterSetValidator "" $destinationPath + CompressArchiveLiteralPathParameterSetValidator $sourcePath "" + CompressArchiveLiteralPathParameterSetValidator "" "" + + CompressArchiveLiteralPathParameterSetValidator $null $null "NoCompression" + + CompressArchiveLiteralPathParameterSetValidator $sourcePath $destinationPath $null + CompressArchiveLiteralPathParameterSetValidator $sourcePath $destinationPath "" + } + + It "Validate errors from Compress-Archive when invalid path (non-existing path / non-filesystem path) is supplied for Path or LiteralPath parameters" { + CompressArchiveInValidPathValidator "$TestDrive\InvalidPath" $TestDrive "$TestDrive\InvalidPath" "ArchiveCmdletPathNotFound,Compress-Archive" + CompressArchiveInValidPathValidator "HKLM:\SOFTWARE" $TestDrive "HKLM:\SOFTWARE" "PathNotFound,Compress-Archive" + CompressArchiveInValidPathValidator "$TestDrive" "$TestDrive\NonExistingDirectory\sample.zip" "$TestDrive\NonExistingDirectory\sample.zip" "ArchiveCmdletPathNotFound,Compress-Archive" + + $path = @("$TestDrive", "$TestDrive\InvalidPath") + CompressArchiveInValidPathValidator $path $TestDrive "$TestDrive\InvalidPath" "ArchiveCmdletPathNotFound,Compress-Archive" + + $path = @("$TestDrive", "HKLM:\SOFTWARE") + CompressArchiveInValidPathValidator $path $TestDrive "HKLM:\SOFTWARE" "PathNotFound,Compress-Archive" + + $invalidUnZipFileFormat = "$TestDrive\Sample.unzip" + CompressArchiveInValidArchiveFileExtensionValidator $TestDrive "$invalidUnZipFileFormat" ".unzip" + + $invalidcabZipFileFormat = "$TestDrive\Sample.cab" + CompressArchiveInValidArchiveFileExtensionValidator $TestDrive "$invalidcabZipFileFormat" ".cab" + } + + It "Validate error from Compress-Archive when archive file already exists and -Update parameter is not specified" { + $sourcePath = "$TestDrive\SourceDir" + $destinationPath = "$TestDrive\ValidateErrorWhenUpdateNotSpecified.zip" + + try + { + "Some Data" > $destinationPath + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + throw "Failed to validate that an archive file format $destinationPath already exists and -Update switch parameter is not specified while running Compress-Archive command." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "ArchiveFileExists,Compress-Archive" + } + } + + It "Validate error from Compress-Archive when duplicate paths are supplied as input to Path parameter" { + $sourcePath = @( + "$TestDrive\SourceDir\Sample-1.txt", + "$TestDrive\SourceDir\Sample-1.txt") + $destinationPath = "$TestDrive\DuplicatePaths.zip" + + try + { + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + throw "Failed to detect that duplicate Path $sourcePath is supplied as input to Path parameter." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "DuplicatePathFound,Compress-Archive" + } + } + + It "Validate error from Compress-Archive when duplicate paths are supplied as input to LiteralPath parameter" { + $sourcePath = @( + "$TestDrive\SourceDir\Sample-1.txt", + "$TestDrive\SourceDir\Sample-1.txt") + $destinationPath = "$TestDrive\DuplicatePaths.zip" + + try + { + Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath + throw "Failed to detect that duplicate Path $sourcePath is supplied as input to LiteralPath parameter." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "DuplicatePathFound,Compress-Archive" + } + } + } + + Context "Compress-Archive - functional test cases" { + It "Validate that a single file can be compressed using Compress-Archive cmdlet" { + $sourcePath = "$TestDrive\SourceDir\ChildDir-1\Sample-3.txt" + $destinationPath = "$TestDrive\SampleSingleFile.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + $destinationPath | Should Exist + } + # This test requires a fix in PS5 to support reading paths with square bracket + It "Validate that Compress-Archive cmdlet can accept LiteralPath parameter with Special Characters" -skip:($PSVersionTable.psversion -lt "5.0") { + $sourcePath = "$TestDrive\SourceDir\ChildDir-1\Sample[]File.txt" + "Some Random Content" | Out-File -LiteralPath $sourcePath + $destinationPath = "$TestDrive\SampleSingleFileWithSpecialCharacters.zip" + try + { + Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath + $destinationPath | Should Exist + } + finally + { + Remove-Item -LiteralPath $sourcePath -Force + } + } + It "Validate that Compress-Archive cmdlet errors out when DestinationPath resolves to multiple locations" { + + New-Item $TestDrive\SampleDir\Child-1 -Type Directory -Force | Out-Null + New-Item $TestDrive\SampleDir\Child-2 -Type Directory -Force | Out-Null + New-Item $TestDrive\SampleDir\Test.txt -Type File -Force | Out-Null + + $destinationPath = "$TestDrive\SampleDir\Child-*\SampleChidArchive.zip" + $sourcePath = "$TestDrive\SampleDir\Test.txt" + try + { + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + throw "Failed to detect that destination $destinationPath can resolve to multiple paths" + } + catch + { + $_.FullyQualifiedErrorId | Should Be "InvalidArchiveFilePath,Compress-Archive" + } + finally + { + Remove-Item -LiteralPath $TestDrive\SampleDir -Force -Recurse + } + } + It "Validate that Compress-Archive cmdlet works when DestinationPath has wild card pattern and resolves to a single valid path" { + + New-Item $TestDrive\SampleDir\Child-1 -Type Directory -Force | Out-Null + New-Item $TestDrive\SampleDir\Test.txt -Type File -Force | Out-Null + + $destinationPath = "$TestDrive\SampleDir\Child-*\SampleChidArchive.zip" + $sourcePath = "$TestDrive\SampleDir\Test.txt" + try + { + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + $destinationPath | Should Exist + } + finally + { + Remove-Item -LiteralPath $TestDrive\SampleDir -Force -Recurse + } + } + # This test requires a fix in PS5 to support reading paths with square bracket + It "Validate that Compress-Archive cmdlet can accept LiteralPath parameter for a directory with Special Characters in the directory name" -skip:($PSVersionTable.psversion -lt "5.0") { + $sourcePath = "$TestDrive\Source[]Dir\ChildDir[]-1" + New-Item $sourcePath -Type Directory | Out-Null + "Some Random Content" | Out-File -LiteralPath "$sourcePath\Sample[]File.txt" + $destinationPath = "$TestDrive\SampleDirWithSpecialCharacters.zip" + try + { + Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath + $destinationPath | Should Exist + } + finally + { + Remove-Item -LiteralPath $sourcePath -Force -Recurse + } + } + It "Validate that Compress-Archive cmdlet can accept DestinationPath parameter with Special Characters" { + $sourcePath = "$TestDrive\SourceDir\ChildDir-1\Sample-3.txt" + $destinationPath = "$TestDrive\Sample[]SingleFile.zip" + try + { + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path -LiteralPath $destinationPath | Should Be $true + } + finally + { + Remove-Item -LiteralPath $destinationPath -Force + } + } + It "Validate that Source Path can be at SystemDrive location" { + $sourcePath = "$env:SystemDrive\SourceDir" + $destinationPath = "$TestDrive\SampleFromSystemDrive.zip" + New-Item $sourcePath -Type Directory | Out-Null + "Some Data" | Out-File -FilePath $sourcePath\SampleSourceFileForArchive.txt + try + { + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + finally + { + del "$sourcePath" -Force -Recurse -ErrorAction SilentlyContinue + } + } + It "Validate that multiple files can be compressed using Compress-Archive cmdlet" { + $sourcePath = @( + "$TestDrive\SourceDir\ChildDir-1\Sample-3.txt", + "$TestDrive\SourceDir\ChildDir-1\Sample-4.txt", + "$TestDrive\SourceDir\ChildDir-2\Sample-5.txt", + "$TestDrive\SourceDir\ChildDir-2\Sample-6.txt") + $destinationPath = "$TestDrive\SampleMultipleFiles.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + It "Validate that multiple files and directories can be compressed using Compress-Archive cmdlet" { + $sourcePath = @( + "$TestDrive\SourceDir\Sample-1.txt", + "$TestDrive\SourceDir\Sample-2.txt", + "$TestDrive\SourceDir\ChildDir-1", + "$TestDrive\SourceDir\ChildDir-2") + $destinationPath = "$TestDrive\SampleMultipleFilesAndDirs.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + It "Validate that a single directory can be compressed using Compress-Archive cmdlet" { + $sourcePath = @("$TestDrive\SourceDir\ChildDir-1") + $destinationPath = "$TestDrive\SampleSingleDir.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + It "Validate that a single directory with multiple files and subdirectories can be compressed using Compress-Archive cmdlet" { + $sourcePath = @("$TestDrive\SourceDir") + $destinationPath = "$TestDrive\SampleSubTree.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + It "Validate that a single directory & multiple files can be compressed using Compress-Archive cmdlet" { + $sourcePath = @( + "$TestDrive\SourceDir\ChildDir-1", + "$TestDrive\SourceDir\Sample-1.txt", + "$TestDrive\SourceDir\Sample-2.txt") + $destinationPath = "$TestDrive\SampleMultipleFilesAndSingleDir.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + + It "Validate that if .zip extension is not supplied as input to DestinationPath parameter, then .zip extension is appended" { + $sourcePath = @("$TestDrive\SourceDir") + $destinationPath = "$TestDrive\SampleNoExtension.zip" + $destinationWithoutExtensionPath = "$TestDrive\SampleNoExtension" + Compress-Archive -Path $sourcePath -DestinationPath $destinationWithoutExtensionPath + Test-Path $destinationPath | Should Be $true + } + It "Validate that relative path can be specified as Path parameter of Compress-Archive cmdlet" { + $sourcePath = ".\SourceDir" + $destinationPath = "RelativePathForPathParameter.zip" + try + { + Push-Location $TestDrive + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + finally + { + Pop-Location + } + } + It "Validate that relative path can be specified as LiteralPath parameter of Compress-Archive cmdlet" { + $sourcePath = ".\SourceDir" + $destinationPath = "RelativePathForLiteralPathParameter.zip" + try + { + Push-Location $TestDrive + Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + finally + { + Pop-Location + } + } + It "Validate that relative path can be specified as DestinationPath parameter of Compress-Archive cmdlet" { + $sourcePath = "$TestDrive\SourceDir" + $destinationPath = ".\RelativePathForDestinationPathParameter.zip" + try + { + Push-Location $TestDrive + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + finally + { + Pop-Location + } + } + It "Validate that -Update parameter makes Compress-Archive to not throw an error if archive file already exists" { + $sourcePath = @("$TestDrive\SourceDir") + $destinationPath = "$TestDrive\SampleUpdateTest.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update + Test-Path $destinationPath | Should Be $true + } + It "Validate -Update parameter by adding a new file to an existing archive file" { + $sourcePath = @("$TestDrive\SourceDir\ChildDir-1") + $destinationPath = "$TestDrive\SampleUpdateAdd1File.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + New-Item $TestDrive\SourceDir\ChildDir-1\Sample-AddedNewFile.txt -Type File | Out-Null + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update + Test-Path $destinationPath | Should Be $true + Validate-ArchiveEntryCount -path $destinationPath -expectedEntryCount 3 + } + + It "Validate that all CompressionLevel values can be used with Compress-Archive cmdlet" { + $sourcePath = "$TestDrive\SourceDir\Sample-1.txt" + + $destinationPath = "$TestDrive\FastestCompressionLevel.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel Fastest + Test-Path $destinationPath | Should Be $true + + $destinationPath = "$TestDrive\OptimalCompressionLevel.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel Optimal + Test-Path $destinationPath | Should Be $true + + $destinationPath = "$TestDrive\NoCompressionCompressionLevel.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel NoCompression + Test-Path $destinationPath | Should Be $true + } + + It "Validate that -Update parameter is modifying a file that already exists in the archive file" { + $filePath = "$TestDrive\SourceDir\ChildDir-1\Sample-3.txt" + + $initialContent = "Initial Content" + $modifiedContent = "Modified Content" + + $initialContent | Set-Content $filePath + + $sourcePath = "$TestDrive\SourceDir" + $destinationPath = "$TestDrive\UpdatingModifiedFile.zip" + + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $True + + $modifiedContent | Set-Content $filePath + + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update + Test-Path $destinationPath | Should Be $True + + ArchiveFileEntryContentValidator "$destinationPath" "SourceDir\ChildDir-1\Sample-3.txt" $modifiedContent + } + + It "Validate Compress-Archive cmdlet in pipleline scenario" { + $destinationPath = "$TestDrive\CompressArchiveFromPipeline.zip" + + # Piping a single file path to Compress-Archive + dir -Path $TestDrive\SourceDir\Sample-1.txt | Compress-Archive -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $True + + # Piping a string directory path to Compress-Archive + "$TestDrive\SourceDir\ChildDir-2" | Compress-Archive -DestinationPath $destinationPath -Update + Test-Path $destinationPath | Should Be $True + + # Piping the output of Get-ChildItem to Compress-Archive + dir "$TestDrive\SourceDir" -Recurse | Compress-Archive -DestinationPath $destinationPath -Update + Test-Path $destinationPath | Should Be $True + } + + It "Validate that Compress-Archive works on ReadOnly files" { + $sourcePath = "$TestDrive\ReadOnlyFile.txt" + $destinationPath = "$TestDrive\TestForReadOnlyFile.zip" + + "Some Content" | Out-File -FilePath $sourcePath + $createdItem = Get-Item $sourcePath + $createdItem.Attributes = 'ReadOnly' + + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + + It "Validate that Compress-Archive generates Verbose messages" { + $sourcePath = "$TestDrive\SourceDir" + $destinationPath = "$TestDrive\Compress-Archive generates VerboseMessages.zip" + + try + { + $ps=[PowerShell]::Create() + $ps.Streams.Error.Clear() + $ps.Streams.Verbose.Clear() + $script = "Import-Module Microsoft.PowerShell.Archive; Compress-Archive -Path $sourcePath -DestinationPath `"$destinationPath`" -CompressionLevel Fastest -Verbose" + $ps.AddScript($script) + $ps.Invoke() + + $ps.Streams.Verbose.Count -gt 0 | Should Be $True + $ps.Streams.Error.Count | Should Be 0 + } + finally + { + $ps.Dispose() + } + } + } + + Context "Expand-Archive - Parameter validation test cases" { + It "Validate non existing archive -Path trows expected error message" { + $sourcePath = "$TestDrive\SourceDir" + $destinationPath = "$TestDrive\ExpandedArchive" + try + { + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath + throw "Expand-Archive succeeded for non existing archive path" + } + catch + { + $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" + } + } + + It "Validate errors from Expand-Archive with NULL & EMPTY values for Path, LiteralPath, DestinationPath parameters" { + ExpandArchiveInvalidParameterValidator $false $null "$TestDrive\SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $false $null $null "ParameterArgumentValidationError,Expand-Archive" + + ExpandArchiveInvalidParameterValidator $false "$TestDrive\SourceDir" $null "ParameterArgumentTransformationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $false "" "$TestDrive\SourceDir" "ParameterArgumentTransformationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $false "$TestDrive\SourceDir" "" "ParameterArgumentTransformationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $false "" "" "ParameterArgumentTransformationError,Expand-Archive" + + ExpandArchiveInvalidParameterValidator $true $null "$TestDrive\SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true $null $null "ParameterArgumentValidationError,Expand-Archive" + + ExpandArchiveInvalidParameterValidator $true "$TestDrive\SourceDir" $null "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "" "$TestDrive\SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "$TestDrive\SourceDir" "" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "" "" "ParameterArgumentValidationError,Expand-Archive" + + ExpandArchiveInvalidParameterValidator $true $null "$TestDrive\SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true $null $null "ParameterArgumentValidationError,Expand-Archive" + + ExpandArchiveInvalidParameterValidator $true "$TestDrive\SourceDir" $null "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "" "$TestDrive\SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "$TestDrive\SourceDir" "" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "" "" "ParameterArgumentValidationError,Expand-Archive" + } + + It "Validate errors from Expand-Archive when invalid path (non-existing path / non-filesystem path) is supplied for Path or LiteralPath parameters" { + try { Expand-Archive -Path "$TestDrive\NonExistingArchive" -DestinationPath "$TestDrive\SourceDir"; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "ArchiveCmdletPathNotFound,Expand-Archive" } + + try { Expand-Archive -Path "HKLM:\SOFTWARE" -DestinationPath "$TestDrive\SourceDir"; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" } + + try { Expand-Archive -LiteralPath "$TestDrive\NonExistingArchive" -DestinationPath "$TestDrive\SourceDir"; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "ArchiveCmdletPathNotFound,Expand-Archive" } + + try { Expand-Archive -LiteralPath "HKLM:\SOFTWARE" -DestinationPath "$TestDrive\SourceDir"; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" } + } + + It "Validate error from Expand-Archive when invalid path (non-existing path / non-filesystem path) is supplied for DestinationPath parameter" { + $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" + $destinationPath = "HKLM:\SOFTWARE" + + try { Expand-Archive -Path $sourcePath -DestinationPath $destinationPath; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "InvalidDirectoryPath,Expand-Archive" } + } + } + + Context "Expand-Archive - functional test cases" { + + It "Validate basic Expand-Archive scenario" { + $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" + $content = "Some Data" + $destinationPath = "$TestDrive\DestDirForBasicExpand" + $files = @("Sample-1.txt", "Sample-2.txt") + + # The files in "$TestDrive\SamplePreCreatedArchive.zip" are precreated. + $fileCreationTimeStamp = Get-Date -Year 2014 -Month 6 -Day 13 -Hour 15 -Minute 50 -Second 20 -Millisecond 0 + + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath + foreach($currentFile in $files) + { + $expandedFile = Join-Path $destinationPath -ChildPath $currentFile + Test-Path $expandedFile | Should Be $True + + # We are validating to make sure that time stamps are preserved in the + # compressed archive are reflected back when the file is expanded. + (dir $expandedFile).LastWriteTime.CompareTo($fileCreationTimeStamp) | Should Be 0 + + Get-Content $expandedFile | Should Be $content + } + } + It "Validate that Expand-Archive cmdlet errors out when DestinationPath resolves to multiple locations" { + New-Item $TestDrive\SampleDir\Child-1 -Type Directory -Force | Out-Null + New-Item $TestDrive\SampleDir\Child-2 -Type Directory -Force | Out-Null + + $destinationPath = "$TestDrive\SampleDir\Child-*" + $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" + try + { + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath + throw "Failed to detect that destination $destinationPath can resolve to multiple paths" + } + catch + { + $_.FullyQualifiedErrorId | Should Be "InvalidDestinationPath,Expand-Archive" + } + finally + { + Remove-Item -LiteralPath $TestDrive\SampleDir -Force -Recurse + } + } + It "Validate that Expand-Archive cmdlet works when DestinationPath resolves has wild card pattern and resolves to a single valid path" { + New-Item $TestDrive\SampleDir\Child-1 -Type Directory -Force | Out-Null + + $destinationPath = "$TestDrive\SampleDir\Child-*" + $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" + try + { + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath + $expandedFiles = Get-ChildItem $destinationPath -Recurse + $expandedFiles.Length | Should BeGreaterThan 1 + } + finally + { + Remove-Item -LiteralPath $TestDrive\SampleDir -Force -Recurse + } + } + It "Validate Expand-Archive scenario where DestinationPath has Special Characters" { + $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" + $content = "Some Data" + $destinationPath = "$TestDrive\DestDir[]Expand" + $files = @("Sample-1.txt", "Sample-2.txt") + + # The files in "$TestDrive\SamplePreCreatedArchive.zip" are precreated. + $fileCreationTimeStamp = Get-Date -Year 2014 -Month 6 -Day 13 -Hour 15 -Minute 50 -Second 20 -Millisecond 0 + + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath + foreach($currentFile in $files) + { + $expandedFile = Join-Path $destinationPath -ChildPath $currentFile + Test-Path -LiteralPath $expandedFile | Should Be $True + + # We are validating to make sure that time stamps are preserved in the + # compressed archive are reflected back when the file is expanded. + (dir -LiteralPath $expandedFile).LastWriteTime.CompareTo($fileCreationTimeStamp) | Should Be 0 + + Get-Content -LiteralPath $expandedFile | Should Be $content + } + } + It "Invoke Expand-Archive with relative path in Path parameter and -Force parameter" { + $sourcePath = ".\SamplePreCreatedArchive.zip" + $destinationPath = "$TestDrive\SomeOtherNonExistingDir\Path" + try + { + Push-Location $TestDrive + + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Force + $expandedFiles = Get-ChildItem $destinationPath -Recurse + $expandedFiles.Length | Should Be 2 + } + finally + { + Pop-Location + } + } + + It "Invoke Expand-Archive with relative path in LiteralPath parameter and -Force parameter" { + $sourcePath = ".\SamplePreCreatedArchive.zip" + $destinationPath = "$TestDrive\SomeOtherNonExistingDir\LiteralPath" + try + { + Push-Location $TestDrive + + Expand-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath -Force + $expandedFiles = Get-ChildItem $destinationPath -Recurse + $expandedFiles.Length | Should Be 2 + } + finally + { + Pop-Location + } + } + + It "Invoke Expand-Archive with non-existing relative directory in DestinationPath parameter and -Force parameter" { + $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" + $destinationPath = ".\SomeOtherNonExistingDir\DestinationPath" + try + { + Push-Location $TestDrive + + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Force + $expandedFiles = Get-ChildItem $destinationPath -Recurse + $expandedFiles.Length | Should Be 2 + } + finally + { + Pop-Location + } + } + + It "Invoke Expand-Archive with unsupported archive format" { + $sourcePath = "$TestDrive\Sample.cab" + $destinationPath = "$TestDrive\UnsupportedArchiveFormatDir" + try + { + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Force + throw "Failed to detect unsupported archive format at $sourcePath" + } + catch + { + $_.FullyQualifiedErrorId | Should Be "NotSupportedArchiveFileExtension,Expand-Archive" + } + } + + It "Invoke Expand-Archive with archive file containing multiple files, directories with subdirectories and empty directories" { + $sourcePath = "$TestDrive\SourceDir" + $archivePath = "$TestDrive\FileAndDirTreeForExpand.zip" + $destinationPath = "$TestDrive\FileAndDirTree" + $sourceList = dir $sourcePath -Name + + Add-CompressionAssemblies + [System.IO.Compression.ZipFile]::CreateFromDirectory($sourcePath, $archivePath) + + Expand-Archive -Path $archivePath -DestinationPath $destinationPath + $extractedList = dir $destinationPath -Name + + Compare-Object -ReferenceObject $extractedList -DifferenceObject $sourceList -PassThru | Should Be $null + } + + It "Validate Expand-Archive cmdlet in pipleline scenario" { + $sourcePath = "$TestDrive\SamplePreCreated*.zip" + $destinationPath = "$TestDrive\PipeToExpandArchive" + + $content = "Some Data" + $files = @("Sample-1.txt", "Sample-2.txt") + + dir $sourcePath | Expand-Archive -DestinationPath $destinationPath + + foreach($currentFile in $files) + { + $expandedFile = Join-Path $destinationPath -ChildPath $currentFile + Test-Path $expandedFile | Should Be $True + Get-Content $expandedFile | Should Be $content + } + } + + It "Validate that Expand-Archive generates Verbose messages" { + $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" + $destinationPath = "$TestDrive\VerboseMessagesInExpandArchive" + + try + { + $ps=[PowerShell]::Create() + $ps.Streams.Error.Clear() + $ps.Streams.Verbose.Clear() + $script = "Import-Module Microsoft.PowerShell.Archive; Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Verbose" + $ps.AddScript($script) + $ps.Invoke() + + $ps.Streams.Verbose.Count -gt 0 | Should Be $True + $ps.Streams.Error.Count | Should Be 0 + } + finally + { + $ps.Dispose() + } + } + + It "Validate that without -Force parameter Expand-Archive generates non-terminating errors without overwriting existing files" { + $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" + $destinationPath = "$TestDrive\NoForceParameterExpandArchive" + + try + { + $ps=[PowerShell]::Create() + $ps.Streams.Error.Clear() + $ps.Streams.Verbose.Clear() + $script = "Import-Module Microsoft.PowerShell.Archive; Expand-Archive -Path $sourcePath -DestinationPath $destinationPath; Expand-Archive -Path $sourcePath -DestinationPath $destinationPath" + $ps.AddScript($script) + $ps.Invoke() + + $ps.Streams.Error.Count -gt 0 | Should Be $True + } + finally + { + $ps.Dispose() + } + } + + It "Validate that without DestinationPath parameter Expand-Archive cmdlet succeeds in expanding the archive" { + $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" + $archivePath = "$TestDrive\NoDestinationPathParameter.zip" + $destinationPath = "$TestDrive\NoDestinationPathParameter" + copy $sourcePath $archivePath -Force + + try + { + Push-Location $TestDrive + + Expand-Archive -Path $archivePath + (dir $destinationPath).Count | Should Be 2 + } + finally + { + Pop-Location + } + } + + It "Validate that without DestinationPath parameter Expand-Archive cmdlet succeeds in expanding the archive when destination directory exists" { + $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" + $archivePath = "$TestDrive\NoDestinationPathParameterDirExists.zip" + $destinationPath = "$TestDrive\NoDestinationPathParameterDirExists" + copy $sourcePath $archivePath -Force + New-Item -Path $destinationPath -ItemType Directory | Out-Null + + try + { + Push-Location $TestDrive + + Expand-Archive -Path $archivePath + (dir $destinationPath).Count | Should Be 2 + } + finally + { + Pop-Location + } + } + } +} \ No newline at end of file diff --git a/test/powershell/Modules/Microsoft.PowerShell.Archive/SamplePreCreatedArchive.archive b/test/powershell/Modules/Microsoft.PowerShell.Archive/SamplePreCreatedArchive.archive new file mode 100644 index 0000000000000000000000000000000000000000..c2aecb417985e0ae3b2fff30c1cfd41f82be5932 GIT binary patch literal 270 zcmWIWW@Zs#U|`^2@TxoOvPh-fTmr}gVICk3PRuRHN!2yfE2${?{a=5E;(W#Fic=jM z54I{!T*%T + + if (test-path $testDirectory) + { + Remove-Item $testDirectory -Force -ea SilentlyContinue -Recurse + } + + # Create testDirectory, and destinationDirectory + New-Item $testDirectory -ItemType Directory -Force | Out-Null + New-Item $destinationDirectory -ItemType Directory -Force | Out-Null + } + + Context "Validate Copy-Item Locally." { + It "Copy-Item -Path $filePath -Destination $destinationFolderPath" { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $filePath -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy-Item -Path $($testObject.SourceDirectory) -Destination $destinationFolderPath -Recurse" { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $testObject.SourceDirectory -Destination $destinationFolderPath -Recurse + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") + $copiedFilePath | should Exist + } + } + } + + Context "Validate Copy-Item to remote session." { + + It "Copy one file to remote session." { + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy one read only file to remote session." { + + $filePath = CreateTestFile -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -Force + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy-Item works for a read only file when '-Force' is not used." { + + $filePath = CreateTestFile -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -Verbose + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy one folder to session Recursively" { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $testObject.SourceDirectory -ToSession $s -Destination $destinationFolderPath -Recurse + + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length + } + } + + It "Copy folder with read only files to remote session recursively." { + $testObject = CreateTestDirectory -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $testObject.SourceDirectory -ToSession $s -Destination $destinationFolderPath -Recurse -Force + + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length + } + } + + It "Copy one file to remote session fails when the remote directory does not exist." { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + $destinationFolderPath = Join-Path $destinationFolderPath "A\B\C\D\E" + $expectedFullyQualifiedErrorId = 'RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand' + + try + { + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -ErrorAction Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId + } + } + + It "Copy folder to remote session recursively works even if the target directory does not exist." { + $testObject = CreateTestDirectory -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + $destinationFolderPath = Join-Path $destinationFolderPath "FoderThatDoesNotExist" + Copy-Item -Path $testObject.SourceDirectory -ToSession $s -Destination $destinationFolderPath -Recurse -Force + + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\FoderThatDoesNotExist") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length + } + } + + It "Copy one empty file to remote session." { + + $filePath = CreateTestFile -emptyFile + $destinationFolderPath = GetDestinationFolderPath + $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") + $copiedFilePath | should Not Exist + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $filePath).Length + } + + It "Copy-Item to session supports alternate data streams." { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + $streamContent = "This content is hidden" + $streamName = "Hidden" + Set-Content -Path $filePath -Value $streamContent -Stream $streamName + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -Verbose + ValidateCopyItemOperationForAlternateDataStream -filePath $filePath -streamName $streamName -expectedStreamContent $streamContent + } + } + + Context "Validate Copy-Item from remote session." { + + It "Copy one file from remote session." { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") + $copiedFilePath | should Not Exist + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy one empty file from remote session." { + + $filePath = CreateTestFile -emptyFile + $destinationFolderPath = GetDestinationFolderPath + $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") + $copiedFilePath | should Not Exist + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy folder from remote session recursively." { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + $files = @(Get-ChildItem $destinationFolderPath -Recurse -Force) + Copy-Item -Path $testObject.SourceDirectory -FromSession $s -Destination $destinationFolderPath -Recurse + + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length + } + } + + It "Copy one file from remote session fails when the target directory does not exist." { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + $destinationFolderPath = Join-Path $destinationFolderPath "A\B\C\D\E" + $expectedFullyQualifiedErrorId = 'CopyItemRemotelyIOError,Microsoft.PowerShell.Commands.CopyItemCommand' + try + { + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath -ErrorAction Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId + } + } + + It "Copy folder from remote session recursively works even if the target directory does not exist." { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + $destinationFolderPath = Join-Path $destinationFolderPath "FoderThatDoesNotExist" + $files = @(Get-ChildItem $destinationFolderPath -Recurse -Force) + Copy-Item -Path $testObject.SourceDirectory -FromSession $s -Destination $destinationFolderPath -Recurse + + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\FoderThatDoesNotExist") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length + } + } + + It "Copy a read only file from a remote session." { + + $filePath = CreateTestFile -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath -Force + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy-Item for a read only file works with no '-force' parameter." { + + $filePath = CreateTestFile -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy-Item -FromSession works even when trying to copy an assembly that is currently being used by another process." { + + $testAssembly = GenerateTestAssembly + $destinationFolderPath = GetDestinationFolderPath + Import-Module $testAssembly.Path -Force + try + { + Copy-Item -Path $testAssembly.Path -FromSession $s -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $testAssembly.Path + } + finally + { + Remove-Module $testAssembly.ModuleName -Force -ea SilentlyContinue + } + } + + It "Copy-Item from session supports alternate data streams." { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + $streamContent = "This content is hidden" + $streamName = "Hidden" + Set-Content -Path $filePath -Value $streamContent -Stream $streamName + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath + ValidateCopyItemOperationForAlternateDataStream -filePath $filePath -streamName $streamName -expectedStreamContent $streamContent + } + } + + Context "Validate Copy-Item Remotely using wildcards" { + + It "Copy-Item from session using wildcards." { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + $sourcePathWithWildcards = "$($testObject.SourceDirectory)\A\*.txt" + Copy-Item -Path $sourcePathWithWildcards -FromSession $s -Destination $destinationFolderPath -Force + + $sourceFiles = @(Get-Item $sourcePathWithWildcards) + foreach ($file in $sourceFiles) + { + $copiedFilePath = Join-Path $destinationFolderPath (Split-Path $file -Leaf) + $copiedFilePath | Should Exist + (Get-Item $copiedFilePath).Length | Should Be (Get-Item $file).Length + } + } + + It "Copy-Item to session using wildcards." { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + $sourcePathWithWildcards = "$($testObject.SourceDirectory)\A\*.txt" + Copy-Item -Path $sourcePathWithWildcards -ToSession $s -Destination $destinationFolderPath -Force + + $sourceFiles = @(Get-Item $sourcePathWithWildcards) + foreach ($file in $sourceFiles) + { + $copiedFilePath = Join-Path $destinationFolderPath (Split-Path $file -Leaf) + $copiedFilePath | Should Exist + (Get-Item $copiedFilePath).Length | Should Be (Get-Item $file).Length + } + } + } + + Context "Validate FullyQualifiedErrorIds for remote source and destination paths." { + + BeforeAll { + # Create test file. + $testFilePath = Join-Path "TestDrive:" "testfile.txt" + if (test-path $testFilePath) + { + Remove-Item $testFilePath -Force -ea SilentlyContinue + } + "File test content" | Out-File $testFilePath -Force + } + + function Test-CopyItemError + { + param ($path, $destination, $expectedFullyQualifiedErrorId, $fromSession = $false) + + if ($fromSession) + { + It "Copy-Item FromSession -Path '$path' throws $expectedFullyQualifiedErrorId" { + try + { + Copy-Item -Path $path -FromSession $s -Destination $destination -ErrorAction Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId + } + } + } + else + { + It "Copy-Item ToSession -Destination '$path' throws $expectedFullyQualifiedErrorId" { + try + { + Copy-Item -Path $path -ToSession $s -Destination $destination -ErrorAction Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId + } + } + } + } + + $invalidSourcePathtestCases = @( + @{ + Path = "HKLM:\SOFTWARE" + Destination = $env:SystemDrive + ExpectedFullyQualifiedErrorId = "NamedParameterNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + @{ + Path = ".\Source" + Destination = $env:SystemDrive + ExpectedFullyQualifiedErrorId = "RemotePathIsNotAbsolute,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + @{ + Path = $env:SystemDrive + "\X\Y\Z" + Destination = $env:SystemDrive + "\A\B\C" + ExpectedFullyQualifiedErrorId = "RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + @{ + Path = $null + Destination = $env:SystemDrive + ExpectedFullyQualifiedErrorId = "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + @{ + Path = '' + Destination = $env:SystemDrive + ExpectedFullyQualifiedErrorId = "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + @{ + Path = "$env:SystemDrive\nonexistdir\*" + Destination = "$env:SystemDrive\psTest" + ExpectedFullyQualifiedErrorId = "RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + ) + + foreach ($testCase in $invalidSourcePathtestCases) { + Test-CopyItemError @testCase + } + + $invalidDestinationPathtestCases = @( + @{ + Path = $testFilePath + Destination = ".\Source" + ExpectedFullyQualifiedErrorId = "RemotePathIsNotAbsolute,Microsoft.PowerShell.Commands.CopyItemCommand" + } + @{ + Path = $testFilePath + Destination = $env:SystemDrive + "\X\A\B\C" + ExpectedFullyQualifiedErrorId = "RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" + } + @{ + Path = $testFilePath + Destination = $null + ExpectedFullyQualifiedErrorId = "CopyItemRemoteDestinationIsNullOrEmpty,Microsoft.PowerShell.Commands.CopyItemCommand" + } + @{ + Path = $testFilePath + Destination = "" + ExpectedFullyQualifiedErrorId = "CopyItemRemoteDestinationIsNullOrEmpty,Microsoft.PowerShell.Commands.CopyItemCommand" + } + @{ + Path = "$env:SystemDrive\nonexistdir\*" + Destination = "$env:SystemDrive\psTest" + ExpectedFullyQualifiedErrorId = "PathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" + } + ) + + foreach ($testCase in $invalidDestinationPathtestCases) { + Test-CopyItemError @testCase + } + } +} + +Describe "Validate Copy-Item error for target sessions not in FullLanguageMode." -Tags "Innerloop", "RI", "P1" { + + BeforeAll { + + $testDirectory = "TestDrive:\" + + # Create the test file and directories. + $source = "$testDirectory\Source" + $destination = "$testDirectory\Destination" + + New-Item $source -ItemType Directory -Force | Out-Null + New-Item $destination -ItemType Directory -Force | Out-Null + + $testFilePath = Join-Path $source "testfile.txt" + "File test content" | Out-File $testFilePath -Force + + # Keep track of the sessions. + $testSessions = @{} + + # Keep track of the session names to be unregistered. + $sessionToUnregister = @() + + $languageModes = @("ConstrainedLanguage", "NoLanguage", "RestrictedLanguage") + $id = (Get-Random).ToString() + + foreach ($languageMode in $languageModes) + { + $sessionName = $languageMode + "_" + $id + $sessionToUnregister += $sessionName + $configFilePath = Join-Path $testDirectory "test.pssc" + + # Create the session. + Write-Host "Creating pssession with '$languageMode' ..." + New-PSSessionConfigurationFile -Path $configFilePath -SessionType Default -LanguageMode $languageMode + Register-PSSessionConfiguration -Name $sessionName -Path $configFilePath -Force | Out-Null + $testSession = New-PSSession -ConfigurationName $sessionName + + # Validate that the session is opened. + $testSession.State | Should Be "Opened" + + # Add the new session to the list. + $testSessions[$languageMode] = $testSession + + # Remove the pssc file. + Remove-Item $configFilePath -Force -ea SilentlyContinue + } + } + + AfterAll { + + $testSessions.Values | Remove-PSSession -ea SilentlyContinue + + $sessionToUnregister | foreach { + Unregister-PSSessionConfiguration -Name $_ -Force -ea SilentlyContinue + } + } + + foreach ($languageMode in $testSessions.Keys) + { + $session = $testSessions[$languageMode] + + It "Copy-Item throws 'SessionIsNotInFullLanguageMode' error for a session in '$languageMode'" { + + # FromSession + try + { + Copy-Item -Path $testFilePath -FromSession $session -Destination $destination -Force -Verbose -ea Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be "SessionIsNotInFullLanguageMode,Microsoft.PowerShell.Commands.CopyItemCommand" + } + + # ToSession + try + { + Copy-Item -Path $testFilePath -ToSession $session -Destination $destination -Force -Verbose -ea Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be "SessionIsNotInFullLanguageMode,Microsoft.PowerShell.Commands.CopyItemCommand" + } + } + } +} + +Describe "Copy-Item can use Recurse and Exclude together" -Tags "RI", "P1" { + + Context "Local and Remote Tests" { + + BeforeAll { + $s = New-PSSession -ComputerName . -ea SilentlyContinue + if (-not $s) + { + throw "Failed to create PSSession for remote copy operations." + } + + $null = New-Item -ItemType Directory -Path "TestDrive:\Parent\Sub" + $null = New-Item -Path "TestDrive:\Parent\p1.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\p2.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\s4.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\Sub\s1.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\Sub\s2.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\Sub\s3.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\Sub\p3.txt" -Value "testcl" + } + + It "can exclude files at sub directory" { + Copy-Item -Path TestDrive:\Parent\* -Recurse -Exclude s*.txt -Destination TestDrive:\Temp -Force + $copiedFiles = Get-ChildItem -Recurse -Path TestDrive:\Temp + $copiedFiles.Count | Should Be 3 + } + + It "can exclude files at sub directory to a session" { + Copy-Item -Path TestDrive:\Parent\* -Recurse -Exclude s*.txt -Destination $TestDrive\Temp2 -Force -ToSession $s + $copiedFiles = Get-ChildItem -Recurse -Path TestDrive:\Temp + $copiedFiles.Count | Should Be 3 + } + + It "can exclude files at sub directory from a session" { + Copy-Item -Path $TestDrive\Parent\* -Recurse -Exclude s*.txt -Destination TestDrive:\Temp3 -FromSession $s + $copiedFiles = Get-ChildItem -Recurse -Path TestDrive:\Temp2 + $copiedFiles.Count | Should Be 3 + } + + AfterAll { + Remove-PSSession -Session $s -ErrorAction SilentlyContinue + } + } +} + +Describe "Copy-Item remotely bug fixes" -Tags "RI", "P1" { + + BeforeAll { + $s = New-PSSession -ComputerName . -ErrorAction SilentlyContinue + if (-not $s) + { + throw "Failed to create PSSession for remote copy operations." + } + + $originalContent = "test file 1 - Source" + $newContent = "This is some new content" + + $null = New-Item -ItemType Directory -Path "TestDrive:\Source" + $null = New-Item -ItemType Directory -Path "TestDrive:\Destination" + } + + AfterAll { + Remove-PSSession -Session $s -ErrorAction SilentlyContinue + } + + BeforeEach { + + # Create the same file in the source and destination + Set-Content -Path "TestDrive:\Source\testFile1.txt" -Value $originalContent -Force + Set-Content -Path "TestDrive:\Destination\testFile1.txt" -Value $originalContent -Force + } + + Context "Copy-Item remotely overwrites a destination file if it exists." { + + BeforeEach { + + # Overwrite the source file + Set-Content -Path "TestDrive:\Source\testFile1.txt" -Value $newContent + } + + It "Copy item -tosession overwrites the content of an existing file." { + + # Copy file to session + Copy-Item -Path "TestDrive:\Source\testFile1.txt" -Destination "$TestDrive\Destination\testFile1.txt" -ToSession $s + + # Validate the the file was overwritten + $fileContent = Get-Content "TestDrive:\Destination\testFile1.txt" -ea SilentlyContinue -Raw + $fileContent | Should Match $newContent + } + + It "Copy item -fromsession overwrites the content of an existing file." { + + # Copy file to session + Copy-Item -Path "$TestDrive\Source\testFile1.txt" -Destination "TestDrive:\Destination\testFile1.txt" -FromSession $s + + # Validate the the file was overwritten + $fileContent = Get-Content "TestDrive:\Destination\testFile1.txt" -ea SilentlyContinue -Raw + $fileContent | Should Match $newContent + } + } + + Context "Copy-Item remotely creates a destination file if it does not exist." { + + BeforeEach { + + if (Test-Path "TestDrive:\AnotherDestination") + { + Remove-Item "TestDrive:\AnotherDestination" -Force -Recurse -ea SilentlyContinue + } + $null = New-Item -ItemType Directory -Path "TestDrive:\AnotherDestination" + + # Ensure the file does not exist + "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" | Should Not Exist + } + + It "Copy-Item -tosession creates the file if it does not exist on the remote destination." { + + # Copy file to session + Copy-Item -Path "TestDrive:\Source\testFile1.txt" -Destination "$TestDrive\AnotherDestination\FileThatDoesNotExist.txt" -ToSession $s + + # Verify that the file was created + "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" | Should Exist + } + + It "Copy-Item -fromsession creates the file if it does not exist on the local machine." { + + # Copy file from session + Copy-Item -Path "$TestDrive\Source\testFile1.txt" -Destination "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" -FromSession $s + + # Verify that the file was created + "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" | Should Exist + } + } +} \ No newline at end of file diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1 new file mode 100644 index 000000000..420c2cfc2 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1 @@ -0,0 +1,26 @@ +# Tests related to TFS item 1370133 [PSUpgrade] Need -NoNewline parameter on Out-File, Add-Content and Set-Content +# Connect request https://connect.microsoft.com/PowerShell/feedback/details/524739/need-nonewline-parameter-on-out-file-add-content-and-set-content + +Describe "Tests for -NoNewline parameter of Out-File, Add-Content and Set-Content" -tags 'P1', 'RI' { + + It "NoNewline parameter works on Out-File" { + $temp = New-TemporaryFile + 1..5 | Out-File $temp.FullName -Encoding 'ASCII' -NoNewline + (Get-Content $temp -Encoding Byte).Count | Should Be 5 + Remove-Item $temp -ErrorAction SilentlyContinue -Force + } + + It "NoNewline parameter works on Set-Content" { + $temp = New-TemporaryFile + Set-Content -Path $temp.FullName -Value 'a','b','c' -Encoding 'ASCII' -NoNewline + (Get-Content $temp -Encoding Byte).Count | Should Be 3 + Remove-Item $temp -ErrorAction SilentlyContinue -Force + } + + It "NoNewline parameter works on Add-Content" { + $temp = New-TemporaryFile + 1..9 | %{Add-Content -Path $temp.FullName -Value $_ -Encoding 'ASCII' -NoNewline} + (Get-Content $temp -Encoding Byte).Count | Should Be 9 + Remove-Item $temp -ErrorAction SilentlyContinue -Force + } +} \ No newline at end of file diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 new file mode 100644 index 000000000..91d05c78d --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 @@ -0,0 +1,218 @@ +# This is a Pester test suite to validate the Format-Hex cmdlet in the Microsoft.PowerShell.Utility module. +# +# Copyright (c) Microsoft Corporation, 2015 +# + +<# + Purpose: + Verify that Format-Hex display the Hexa decmial value for the input data. + + Action: + Run Format-Fex. + + Expected Result: + Hexa decimal equivalent of the input data is displayed. +#> + +Describe "FormatHex" -tags 'DRT' { + + New-Item TestDrive:\FormatHexDataDir -Type Directory -Force | Out-Null + $inputFile = "TestDrive:\FormatHexDataDir\SourceFile-1.txt" + $inputText = 'Hello World' + Set-Content -Value $inputText -Path $inputFile + $inputFile2 = "TestDrive:\FormatHexDataDir\SourceFile-2.txt" + $inputText2 = 'This is a bit more text' + Set-Content -Value $inputText2 -Path $inputFile2 + + # This test is to validate to pipeline support in Format-Hex cmdlet. + It "ValidatePipelineSupport" { + + # InputObject Parameter set should get invoked and + # the input data should be treated as string. + $result = $inputText | Format-Hex + $result | Should Not Be $null + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText) | Should Be $true + } + + # This test is to validate to pipeline support in Format-Hex cmdlet. + It "ValidateByteArrayInputSupport" { + + # InputObject Parameter set should get invoked and + # the input data should be treated as byte[]. + $inputBytes = [System.Text.Encoding]::ASCII.GetBytes($inputText) + + $result = Format-Hex -InputObject $inputBytes + $result | Should Not Be $null + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText) | Should Be $true + } + + # This test is to validate to input given through Path paramter set in Format-Hex cmdlet. + It "ValidatePathParameterSet" { + + $result = Format-Hex -Path $inputFile + $result | Should Not Be $null + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText) | Should Be $true + } + + # This test is to validate to Path paramter set is considered as default in Format-Hex cmdlet. + It "ValidatePathAsDefaultParameterSet" { + + $result = Format-Hex $inputFile + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText) | Should Be $true + } + + # This test is to validate to input given through LiteralPath paramter set in Format-Hex cmdlet. + It "ValidateLiteralPathParameterSet" { + + $result = Format-Hex -LiteralPath $inputFile + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText) | Should Be $true + } + + # This test is to validate to input given through pipeline. The input being piped from results of Get-hildItem + It "ValidateFileInfoPipelineInput" { + + $result = Get-ChildItem $inputFile | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText) | Should Be $true + } + + # This test is to validate Encoding formats functionality of Format-Hex cmdlet. + It "ValidateEncodingFormats" { + + $result = Format-Hex -InputObject $inputText -Encoding ASCII + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText) | Should Be $true + } + + # This test is to validate that integers can be piped to the format-hex + It "ValidateIntegerInput" { + + $result = 1,2,3,4 | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + # whitespace sensitive + $actualResult | should be "00000000 01 02 03 04 .... " + } + + # This test is to validate that integers can be piped to the format-hex + # and properly represented as characters in the string + It "ValidateIntegerInputThatPresentAsCharacters" { + + $result = 65..68 | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + # whitespace sensitive + $actualResult | should be "00000000 41 42 43 44 ABCD " + } + + # This test is to validate that integers can be piped to the format-hex + It "ValidateIntegerRawInput" { + + $result = 1,2,3,4 | Format-Hex -Raw + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + # whitespace sensitive + $actualResult | should be "00000000 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 ................" + } + + # handle int64 + It "ValidateInteger64" { + + $result = [int64]::MaxValue | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + # whitespace sensitive + $actualResult | Should Match "00000000 FF FF FF FF FF FF FF 7F ." + } + + # handle bytes, int16, int32, and int64 + It "Validate combined and reduced number formatting" { + $b = 65 # fits in a byte + $i16 = 32767 # fits in an int16 + $i32 = 2147483647 # an int32 + $i64 = 9223372036854775807 # an int64 + $result = $b,$i16,$i32,$i64 | format-Hex + $result.GetType().Name | should be 'ByteCollection' + $actualResult = $result.ToString() + $actualResult | should Match "00000000 41 FF 7F FF FF FF 7F FF FF FF FF FF FF FF 7F A" + } + + # handle bytes, int16, int32, and int64 + It "Validate combined and with raw number formatting" { + $b = 65 # fits in a byte + $i16 = 32767 # fits in an int16 + $i32 = 2147483647 # an int32 + $i64 = 9223372036854775807 # an int64 + # this will cause 2 lines to be emitted + $result = $b,$i16,$i32,$i64 | format-Hex -Raw + $result[0].GetType().Name | should be 'ByteCollection' + $result[1].GetType().Name | should be 'ByteCollection' + $result0 = $result[0].ToString() + $result0 | should match "00000000 41 00 00 00 FF 7F 00 00 FF FF FF 7F FF FF FF FF A" + $result1 = $result[1].ToString() + $result1 | should match "00000010 FF FF FF 7F .." + } + + # This test is to validate that streamed text does not have buffer underrun problems + It "ValidateEachBufferHasCorrectContentForStreamingText" { + $result = "a" * 30 | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() -split "`r`n" + $actualResult.Count | should be 2 + $actualResult[0].ToString() | Should be "00000000 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaaaa" + $actualResult[1].ToString() | Should be "00000010 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaa " + } + + # This test is to validate that files do not have buffer underrun problems + It "ValidateEachBufferHasCorrectContentForFiles" { + $result = Format-Hex -path $InputFile2 + $result | Should Not BeNullOrEmpty + $result.Count | should be 2 + $result[0].ToString() | Should be "00000000 54 68 69 73 20 69 73 20 61 20 62 69 74 20 6D 6F This is a bit mo" + $result[1].ToString() | Should be "00000010 72 65 20 74 65 78 74 0D 0A re text.. " + } + + # This test ensures that if we stream bytes from a file, the output is correct + It "ValidateStreamOfBytesFromFileHasProperOutput" { + $result = Get-Content $InputFile -Encoding Byte | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be "ByteCollection" + $result.ToString() | Should be "00000000 48 65 6C 6C 6F 20 57 6F 72 6C 64 0D 0A Hello World.. " + } + + # This test is to validate the alias for Format-Hex cmdlet. + It "ValidateCmdletAlias" { + + try + { + $result = Get-Command fhx -ErrorAction Stop + $result | Should Not BeNullOrEmpty + $result.CommandType.ToString() | Should Be "Alias" + } + catch + { + $_ | Should BeNullOrEmpty + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 new file mode 100644 index 000000000..7c1a2f974 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 @@ -0,0 +1,65 @@ +Describe "Using delimiters with Export-CSV and Import-CSV behave correctly" -tags P1 { + BeforeAll { + # note, we will not use "," as that's the default for CSV + $delimiters = "/", " ", "@", "#", "$", "\", "&", "(", ")", + "{", "}", "|", "<", ">", ";", "'", + '"', "~", "!", "%", "^", "*", "_", "+", ":", + "?", "-", "=", "[", "]", "." + $defaultDelimiter = [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator + $d = get-date + $testCases = @( + foreach($del in $delimiters) + { + @{ Delimiter = $del; Data = $d; ExpectedResult = $d.Ticks } + } + ) + } + AfterEach { + [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator = $defaultDelimiter + remove-item -force -ea silentlycontinue TESTDRIVE:/file.csv + } + + It "Disallow use of null delimiter" { + $d | export-csv TESTDRIVE:/file.csv + { import-csv -path TESTDRIVE:/file.csv -delimiter $null } | Should Throw "Delimiter" + } + + It "Disallow use of delimiter with useCulture parameter" { + $d | export-csv TESTDRIVE:/file.csv + { import-csv -path TESTDRIVE:/file.csv -useCulture "," } | Should Throw "','" + } + + It "Imports the same properties as exported" { + $a = [pscustomobject]@{ a = 1; b = 2; c = 3 } + $a | export-Csv TESTDRIVE:/file.csv + $b = import-csv TESTDRIVE:/file.csv + @($b.psobject.properties).count | should be 3 + $b.a | Should be $a.a + $b.b | Should be $a.b + $b.c | Should be $a.c + } + + # parameter generated tests + It 'Delimiter with CSV import will fail correctly when culture does not match' -testCases $testCases { + param ($delimiter, $Data, $ExpectedResult) + [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator = $delimiter + $Data | export-CSV TESTDRIVE:\File.csv -useCulture + $i = Import-CSV TESTDRIVE:\File.csv + $i.Ticks | Should Not Be $ExpectedResult + } + + It 'Delimiter with CSV import will succeed when culture matches export' -testCases $testCases { + param ($delimiter, $Data, $ExpectedResult) + [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator = $delimiter + $Data | export-CSV TESTDRIVE:\File.csv -useCulture + $i = Import-CSV TESTDRIVE:\File.csv -useCulture + $i.Ticks | Should Be $ExpectedResult + } + + It 'Delimiter with CSV import will succeed when delimiter is used explicitly' -testCases $testCases { + param ($delimiter, $Data, $ExpectedResult) + $Data | export-CSV TESTDRIVE:\File.csv -delimiter $delimiter + $i = Import-CSV TESTDRIVE:\File.csv -delimiter $delimiter + $i.Ticks | Should Be $ExpectedResult + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1 new file mode 100644 index 000000000..9e6138387 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1 @@ -0,0 +1,54 @@ +Describe "GetDateFormatUpdates" -tags 'P1', 'RI' { + + It "Verifies that FileDate format works" { + $date = Get-Date + $expectedFormat = "{0:yyyyMMdd}" -f $date + $actualFormat = Get-Date -Date $date -Format FileDate + + $actualFormat | Should be $expectedFormat + } + + It "Verifies that FileDateUniversal format works" { + $date = (Get-Date).ToUniversalTime() + $expectedFormat = "{0:yyyyMMddZ}" -f $date + $actualFormat = Get-Date -Date $date -Format FileDateUniversal + + $actualFormat | Should be $expectedFormat + } + + It "Verifies that FileDateTime format works" { + $date = Get-Date + $expectedFormat = "{0:yyyyMMddTHHmmssffff}" -f $date + $actualFormat = Get-Date -Date $date -Format FileDateTime + + $actualFormat | Should be $expectedFormat + } + + It "Verifies that FileDateTimeUniversal format works" { + $date = (Get-Date).ToUniversalTime() + $expectedFormat = "{0:yyyyMMddTHHmmssffffZ}" -f $date + $actualFormat = Get-Date -Date $date -Format FileDateTimeUniversal + + $actualFormat | Should be $expectedFormat + } + +} + +Describe "GetRandomMiscTests" -tags 'P1', 'RI' { + It "Shouldn't overflow when using max range" { + + $hadError = $false + + try + { + ## Don't actually need to validate + Get-Random -Minimum ([Int32]::MinValue) -Maximum ([Int32]::MaxValue) -ErrorAction Stop + } + catch + { + $hadError = $true + } + + $hadError | Should be $false + } +} \ No newline at end of file diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1 new file mode 100644 index 000000000..1a912a27b --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1 @@ -0,0 +1,19 @@ +Describe -Tags "Unit","DRT" "New-Guid" { + + It "returns a new guid" { + $guid = New-Guid + $guid.GetType().FullName | Should Be "System.Guid" + } + + It "should not be all zeros" { + $guid = New-Guid + $guid.ToString() | Should Not Be "00000000-0000-0000-0000-000000000000" + } + + It "should return different guids with each call" { + $guid1 = New-Guid + $guid2 = New-Guid + $guid1.ToString() | Should Not Be $guid2.ToString() + } +} + diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1 new file mode 100644 index 000000000..e705cb4a2 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1 @@ -0,0 +1,38 @@ +# This is a Pester test suite to validate the New-TemporaryFile cmdlet in the Microsoft.PowerShell.Utility module. +# +# Copyright (c) Microsoft Corporation, 2015 +# + +<# + Purpose: + Verify that New-TemporaryFile creates a temporary file. + + Action: + Run New-TemporaryFile. + + Expected Result: + A FileInfo object for the temporary file is returned. +#> + +Describe "NewTemporaryFile" -tags 'DRT' { + + It "creates a new temporary file" { + $tempFile = New-TemporaryFile + + Test-Path $tempFile | Should be $true + $tempFile.GetType().Name | Should be "FileInfo" + + if(Test-Path $tempFile) + { + Remove-Item $tempFile -ErrorAction SilentlyContinue -Force + } + } + + It "with WhatIf does not create a file" { + New-TemporaryFile -WhatIf | Should Be $null + } + + It "has an OutputType of System.IO.FileInfo" { + (Get-Command New-TemporaryFile).OutputType | Should Be "System.IO.FileInfo" + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.JsonTests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.JsonTests.ps1 new file mode 100644 index 000000000..913ee65e3 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.JsonTests.ps1 @@ -0,0 +1,1465 @@ +# +# Copyright (c) Microsoft Corporation, 2015 +# +# This is a Pester test suite which validate the Json cmdlets. +# + +# +# This 'Describe' is for tests that were converted from utscripts (SDXROOT/admin/monad/tests/monad/DRT/utscripts) +# and C# tests (SDXROOT/admin/monad/tests/monad/DRT/commands/utility/UnitTests) to Pester. +# +Describe "Json Tests" -Tags "RI", "P1" { + + BeforeAll { + + function ValidateSampleObject + { + param ($result, [switch]$hasEmbeddedSampleObject ) + + Write-Verbose "validating deserialized SampleObject" -Verbose + $result.SampleInt | Should Be 98765 + $result.SampleString | Should Match "stringVal" + $result.SampleArray.Count | Should Be 2 + $result.SampleTrue | Should Be $true + $result.SampleFalse | Should Be $false + $result.SampleNull | Should Be $null + $result.SampleFloat | Should Be 9.8765E+43 + + if ($hasEmbeddedSampleObject) + { + Write-Verbose "validating deserialized Embedded SampleObject" -Verbose + ValidateSampleObject -result $result.SampleObject + } + } + + } + + Context "ConvertTo-Json Bug Fixes" { + + It "ConvertTo-JSON should not have hard coded english error message" { + + # Test follow-up for bug WinBlue: 163372 - ConvertTo-JSON has hard coded english error message. + $process = Get-Process -Id $PID + $hash = @{ $process = "def" } + $expectedFullyQualifiedErrorId = "NonStringKeyInDictionary,Microsoft.PowerShell.Commands.ConvertToJsonCommand" + + try + { + ConvertTo-Json -InputObject $hash + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId + } + } + + It "ConvertTo-Json should handle terms with double quotes" { + + # Test follow-up for bug WinBlue: 11484 - ConvertTo-Json can't handle terms with double quotes. + + $notcompressed = ConvertTo-JSON @{ FirstName = 'Hello " World' } + $compressed = ConvertTo-Json @{ FirstName = 'Hello " World' } -Compress + $valueFromNotCompressedResult = ConvertFrom-Json -InputObject $notcompressed + $valueFromCompressedResult = ConvertFrom-Json -InputObject $compressed + + $valueFromNotCompressedResult.FirstName | Should Match $valueFromCompressedResult.FirstName + } + + It "Convertto-Json should handle Enum based on Int64" { + + # Test follow-up for bug Win8: 378368 Convertto-Json problems with Enum based on Int64. + $src = @" +namespace Bug378368 +{ + public enum TestEnum : ulong + { + One = 1, + Two = 2 + } + + public enum TestEnum1 : long + { + One = 1, + Two = 2 + } + + public enum TestEnum2 : int + { + One = 1, + Two = 2 + } + + public class Test + { + public TestEnum TestEnum + { + get { return testEnum; } + set { testEnum = value; } + } + + private TestEnum testEnum = TestEnum.One; + + public TestEnum1 TestEnum1 + { + get { return testEnum1; } + set { testEnum1 = value; } + } + + private TestEnum1 testEnum1 = TestEnum1.Two; + + public TestEnum2 TestEnum2 + { + get { return testEnum2; } + set { testEnum2 = value; } + } + + private TestEnum2 testEnum2 = TestEnum2.One; + } +} +"@ + Add-Type $src + $op = new-object Bug378368.Test | convertto-json | convertfrom-json + $op.TestEnum | Should Be "One" + $op.TestEnum1 | Should Be "Two" + $op.TestEnum2 | Should Be 1 + } + + It "Test followup for Windows 8 bug 121627" { + + $JsonString = Get-Command Get-help |Select-Object Name, Noun, Verb| ConvertTo-Json + $actual = ConvertFrom-Json $JsonString + + $actual.Name | Should Be "Get-Help" + $actual.Noun | Should Be "Help" + $actual.Verb | Should Be "Get" + } + } + + Context "ConvertFrom and ConvertTo on JsonObject Tests" { + + It "Convert dictionary to PSObject" { + + $response = ConvertFrom-Json '{"d":{"__type":"SimpleJsonObject","Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' + $response.d.Name.First | Should Match "Joel" + } + + It "Convert to Json using PSOjbect" { + + $response = ConvertFrom-Json '{"d":{"__type":"SimpleJsonObject","Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' + + $response2 = ConvertTo-Json -InputObject $response -ErrorAction Continue + $response2 = ConvertTo-Json -InputObject $response -ErrorAction Inquire + $response2 = ConvertTo-Json -InputObject $response -ErrorAction SilentlyContinue + $response2 = ConvertTo-Json -InputObject $response -Depth 2 -Compress + $response2 | Should Be '{"d":{"Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' + + $response2 = ConvertTo-Json -InputObject $response -Depth 1 -Compress + $nameString = [System.Management.Automation.LanguagePrimitives]::ConvertTo($response.d.Name, [string]) + $response2 | Should Be "{`"d`":{`"Name`":`"$nameString`",`"Greeting`":`"Hello`"}}" + + $result1 = @" +{ + "d": { + "Name": { + "First": "Joel", + "Last": "Wood" + }, + "Greeting": "Hello" + } +} +"@ + $response2 = ConvertTo-Json -InputObject $response -Depth 2 + $response2 | Should Match $result1 + + $result2 = @" +{ + "d": { + "Name": "$nameString", + "Greeting": "Hello" + } +} +"@ + $response2 = ConvertTo-Json -InputObject $response -Depth 1 + $response2 | Should Match $result2 + + $arraylist = new-Object System.Collections.ArrayList + [void]$arraylist.Add("one") + [void]$arraylist.Add("two") + [void]$arraylist.Add("three") + $response2 = ConvertTo-Json -InputObject $arraylist -Compress + $response2 | Should Be '["one","two","three"]' + + $result3 = @" +[ + "one", + "two", + "three" +] +"@ + $response2 = ConvertTo-Json -InputObject $arraylist + $response2 | Should Be $result3 + + $response2 = $arraylist | ConvertTo-Json + $response2 | Should Be $result3 + } + + It "Convert to Json using hashtable" { + + $nameHash = @{First="Joe1";Last="Wood"} + $dHash = @{Name=$nameHash; Greeting="Hello"} + $rootHash = @{d=$dHash} + $response3 = ConvertTo-Json -InputObject $rootHash -Depth 2 -Compress + $response3 | Should Be '{"d":{"Greeting":"Hello","Name":{"Last":"Wood","First":"Joe1"}}}' + + $response3 = ConvertTo-Json -InputObject $rootHash -Depth 1 -Compress + $response3 | Should Be '{"d":{"Greeting":"Hello","Name":"System.Collections.Hashtable"}}' + + $result4 = @" +{ + "d": { + "Greeting": "Hello", + "Name": { + "Last": "Wood", + "First": "Joe1" + } + } +} +"@ + $response3 = ConvertTo-Json -InputObject $rootHash -Depth 2 + $response3 | Should Be $result4 + + $result5 = @" +{ + "d": { + "Greeting": "Hello", + "Name": "System.Collections.Hashtable" + } +} +"@ + $response3 = ConvertTo-Json -InputObject $rootHash -Depth 1 + $response3 | Should Be $result5 + } + + It "Convert from Json allows an empty string" { + + $emptyStringResult = ConvertFrom-Json "" + $emptyStringResult | Should Be $null + } + } + + Context "JsonObject Tests" { + + It "AddMember on JsonObject" { + + # create a Version object + $versionObject = New-Object System.Version 2, 3, 4, 14 + + # add a NoteProperty member called Note with a text note + $versionObject | Add-Member -MemberType NoteProperty -Name Note -Value "a version object" + + # add an AliasProperty called Rev as an alias to the Revison property + $versionObject | Add-Member -MemberType AliasProperty -Name Rev -Value Revision + + # add a ScriptProperty called IsOld which returns whether the version is an older version + $versionObject | Add-Member -MemberType ScriptProperty -Name IsOld -Value { ($this.Major -le 3) } + + $jstr = ConvertTo-Json $versionObject + + # convert the JSON string to a JSON object + $json = ConvertFrom-Json $jstr + + # Check the basic properties + $json.Major | Should Be 2 + $json.Minor | Should Be 3 + $json.Build | Should Be 4 + $json.Revision | Should Be 14 + $json.Note | Should Match "a version object" + + # Check the AliasProperty + $json.Rev | Should Be $json.Revision + + # Check the ScriptProperty + $json.IsOld | Should Be $true + } + + It "ConvertFrom-Json with a key value pair" { + + $json = "{name:1}" + $result = ConvertFrom-Json $json + $result.name | Should Be 1 + } + + It "ConvertFrom-Json with a simple array" { + + $json = "[1,2,3,4,5,6]" + $result = ConvertFrom-Json $json + $result.Count | Should Be 6 + $result.GetType().BaseType.fullname | Should Be "System.Array" + } + + It "ConvertFrom-Json with a float value" { + + $json = '{"SampleFloat1":1.2345E67, "SampleFloat2":-7.6543E-12}' + $result = ConvertFrom-Json $json + + $sampleFloat1 = Invoke-Expression 1.2345E67 + $result.SampleFloat1 | Should Be $sampleFloat1 + + $sampleFloat2 = Invoke-Expression -7.6543E-12 + $result.SampleFloat2 | Should Be $sampleFloat2 + } + + It "ConvertFrom-Json hash table nested in array" { + + $json = "['one', 'two', {'First':1,'Second':2,'Third':['Five','Six', 'Seven']}, 'four']" + $result = ConvertFrom-Json $json + + $result.Count | Should Be 4 + $result[0] | Should Be "one" + $result[1] | Should Be "two" + $result[3] | Should Be "four" + + $hash = $result[2] + $hash.First | Should Be 1 + $hash.Second | Should Be 2 + $hash.Third.Count | Should Be 3 + $hash.Third[0] | Should Be "Five" + $hash.Third[1] | Should Be "Six" + $hash.Third[2] | Should Be "Seven" + } + + It "ConvertFrom-Json array nested in hash table" { + + $json = '{"First":["one", "two", "three"], "Second":["four", "five"], "Third": {"blah": 4}}' + $result = ConvertFrom-Json $json + + $result.First.Count | Should Be 3 + $result.First[0] | Should Be "one" + $result.First[1] | Should Be "two" + $result.First[2] | Should Be "three" + + $result.Second.Count | Should Be 2 + $result.Second[0] | Should Be "four" + $result.Second[1] | Should Be "five" + + $result.Third.blah | Should Be "4" + } + + It "ConvertFrom-Json case insensitive test" { + + $json = '{"sAMPleValUE":12345}' + $result = ConvertFrom-Json $json + + $result.SampleValue | Should Be 12345 + } + + + It "ConvertFrom-Json sample values" { + + $json = '{"SampleInt":98765, "SampleString":"stringVal","SampleArray":[2,"two"], "SampleTrue":true, "SampleFalse":false,"SampleNull":null, "SampleFloat":9.8765E43}' + $result = ConvertFrom-Json $json + + # Validate the result object + ValidateSampleObject -result $result + + + $json = '{"SampleInt":98765, "SampleString":"stringVal","SampleArray":[2,"two"], "SampleTrue":true, ' + + '"SampleFalse":false,"SampleNull":null, "SampleFloat":9.8765E43, "SampleObject":'+ + '{"SampleInt":98765, "SampleString":"stringVal","SampleArray":[2,"two"], '+ + '"SampleTrue":true, "SampleFalse":false,"SampleNull":null, "SampleFloat":9.8765E43}}' + + # Validate the result object + $result = ConvertFrom-Json $json + ValidateSampleObject -result $result -hasEmbeddedSampleObject + } + + It "ConvertFrom-Json with special characters" { + + $json = '{"SampleValue":"\"\\\b\f\n\r\t\u4321\uD7FF"}' + $result = ConvertFrom-Json $json + $result.SampleValue[0] | Should Be '"' + $result.SampleValue[1] | Should Be '\' + $result.SampleValue[2] | Should Be 0x8 + $result.SampleValue[3] | Should Be 0xC + $result.SampleValue[4] | Should Be 0xA + $result.SampleValue[5] | Should Be 0xD + $result.SampleValue[6] | Should Be 0x9 + $result.SampleValue[7] | Should Be 0x4321 + $result.SampleValue[8] | Should Be 0xD7FF + } + } +} + +# This Describe is for new Json tests +# +Describe "Validate Json serialization" -Tags "BVT" { + + Context "Validate Json serialization ascii values" { + + $testCases = @( + @{ + TestInput = 0 + ToJson = 'null' + FromJson = '' + } + @{ + TestInput = 1 + ToJson = '"\u0001"' + FromJson = '' + } + @{ + TestInput = 2 + ToJson = '"\u0002"' + FromJson = '' + } + @{ + TestInput = 3 + ToJson = '"\u0003"' + FromJson = '' + } + @{ + TestInput = 4 + ToJson = '"\u0004"' + FromJson = '' + } + @{ + TestInput = 5 + ToJson = '"\u0005"' + FromJson = '' + } + @{ + TestInput = 6 + ToJson = '"\u0006"' + FromJson = '' + } + @{ + TestInput = 7 + ToJson = '"\u0007"' + FromJson = '' + } + @{ + TestInput = 8 + ToJson = '"\b"' + FromJson = '' + } + @{ + TestInput = 9 + ToJson = '"\t"' + FromJson = ' ' + } + @{ + TestInput = 10 + ToJson = '"\n"' + FromJson = "`n" + } + @{ + TestInput = 11 + ToJson = '"\u000b"' + FromJson = ' ' + } + @{ + TestInput = 12 + ToJson = '"\f"' + FromJson = ' ' + } + @{ + TestInput = 13 + ToJson = '"\r"' + FromJson = '' + } + @{ + TestInput = 14 + ToJson = '"\u000e"' + FromJson = '' + } + @{ + TestInput = 15 + ToJson = '"\u000f"' + FromJson = '' + } + @{ + TestInput = 16 + ToJson = '"\u0010"' + FromJson = '' + } + @{ + TestInput = 17 + ToJson = '"\u0011"' + FromJson = '' + } + @{ + TestInput = 18 + ToJson = '"\u0012"' + FromJson = '' + } + @{ + TestInput = 19 + ToJson = '"\u0013"' + FromJson = '' + } + @{ + TestInput = 20 + ToJson = '"\u0014"' + FromJson = '' + } + @{ + TestInput = 21 + ToJson = '"\u0015"' + FromJson = '' + } + @{ + TestInput = 22 + ToJson = '"\u0016"' + FromJson = '' + } + @{ + TestInput = 23 + ToJson = '"\u0017"' + FromJson = '' + } + @{ + TestInput = 24 + ToJson = '"\u0018"' + FromJson = '' + } + @{ + TestInput = 25 + ToJson = '"\u0019"' + FromJson = '' + } + @{ + TestInput = 26 + ToJson = '"\u001a"' + FromJson = '' + } + @{ + TestInput = 27 + ToJson = '"\u001b"' + FromJson = '' + } + @{ + TestInput = 28 + ToJson = '"\u001c"' + FromJson = '' + } + @{ + TestInput = 29 + ToJson = '"\u001d"' + FromJson = '' + } + @{ + TestInput = 30 + ToJson = '"\u001e"' + FromJson = '' + } + @{ + TestInput = 31 + ToJson = '"\u001f"' + FromJson = '' + } + @{ + TestInput = 32 + ToJson = '" "' + FromJson = ' ' + } + @{ + TestInput = 33 + ToJson = '"!"' + FromJson = '!' + } + @{ + TestInput = 34 + ToJson = '"\""' + FromJson = '"' + } + @{ + TestInput = 35 + ToJson = '"#"' + FromJson = '#' + } + @{ + TestInput = 36 + ToJson = '"$"' + FromJson = '$' + } + @{ + TestInput = 37 + ToJson = '"%"' + FromJson = '%' + } + @{ + TestInput = 38 + ToJson = '"\u0026"' + FromJson = '&' + } + @{ + TestInput = 39 + ToJson = '"\u0027"' + FromJson = "'" + } + @{ + TestInput = 40 + ToJson = '"("' + FromJson = '(' + } + @{ + TestInput = 41 + ToJson = '")"' + FromJson = ')' + } + @{ + TestInput = 42 + ToJson = '"*"' + FromJson = '*' + } + @{ + TestInput = 43 + ToJson = '"+"' + FromJson = '+' + } + @{ + TestInput = 44 + ToJson = '","' + FromJson = ',' + } + @{ + TestInput = 45 + ToJson = '"-"' + FromJson = '-' + } + @{ + TestInput = 46 + ToJson = '"."' + FromJson = '.' + } + @{ + TestInput = 47 + ToJson = '"/"' + FromJson = '/' + } + @{ + TestInput = 48 + ToJson = '"0"' + FromJson = '0' + } + @{ + TestInput = 49 + ToJson = '"1"' + FromJson = '1' + } + @{ + TestInput = 50 + ToJson = '"2"' + FromJson = '2' + } + @{ + TestInput = 51 + ToJson = '"3"' + FromJson = '3' + } + @{ + TestInput = 52 + ToJson = '"4"' + FromJson = '4' + } + @{ + TestInput = 53 + ToJson = '"5"' + FromJson = '5' + } + @{ + TestInput = 54 + ToJson = '"6"' + FromJson = '6' + } + @{ + TestInput = 55 + ToJson = '"7"' + FromJson = '7' + } + @{ + TestInput = 56 + ToJson = '"8"' + FromJson = '8' + } + @{ + TestInput = 57 + ToJson = '"9"' + FromJson = '9' + } + @{ + TestInput = 58 + ToJson = '":"' + FromJson = ':' + } + @{ + TestInput = 59 + ToJson = '";"' + FromJson = ';' + } + @{ + TestInput = 60 + ToJson = '"\u003c"' + FromJson = '<' + } + @{ + TestInput = 61 + ToJson = '"="' + FromJson = '=' + } + @{ + TestInput = 62 + ToJson = '"\u003e"' + FromJson = '>' + } + @{ + TestInput = 63 + ToJson = '"?"' + FromJson = '?' + } + @{ + TestInput = 64 + ToJson = '"@"' + FromJson = '@' + } + @{ + TestInput = 65 + ToJson = '"A"' + FromJson = 'A' + } + @{ + TestInput = 66 + ToJson = '"B"' + FromJson = 'B' + } + @{ + TestInput = 67 + ToJson = '"C"' + FromJson = 'C' + } + @{ + TestInput = 68 + ToJson = '"D"' + FromJson = 'D' + } + @{ + TestInput = 69 + ToJson = '"E"' + FromJson = 'E' + } + @{ + TestInput = 70 + ToJson = '"F"' + FromJson = 'F' + } + @{ + TestInput = 71 + ToJson = '"G"' + FromJson = 'G' + } + @{ + TestInput = 72 + ToJson = '"H"' + FromJson = 'H' + } + @{ + TestInput = 73 + ToJson = '"I"' + FromJson = 'I' + } + @{ + TestInput = 74 + ToJson = '"J"' + FromJson = 'J' + } + @{ + TestInput = 75 + ToJson = '"K"' + FromJson = 'K' + } + @{ + TestInput = 76 + ToJson = '"L"' + FromJson = 'L' + } + @{ + TestInput = 77 + ToJson = '"M"' + FromJson = 'M' + } + @{ + TestInput = 78 + ToJson = '"N"' + FromJson = 'N' + } + @{ + TestInput = 79 + ToJson = '"O"' + FromJson = 'O' + } + @{ + TestInput = 80 + ToJson = '"P"' + FromJson = 'P' + } + @{ + TestInput = 81 + ToJson = '"Q"' + FromJson = 'Q' + } + @{ + TestInput = 82 + ToJson = '"R"' + FromJson = 'R' + } + @{ + TestInput = 83 + ToJson = '"S"' + FromJson = 'S' + } + @{ + TestInput = 84 + ToJson = '"T"' + FromJson = 'T' + } + @{ + TestInput = 85 + ToJson = '"U"' + FromJson = 'U' + } + @{ + TestInput = 86 + ToJson = '"V"' + FromJson = 'V' + } + @{ + TestInput = 87 + ToJson = '"W"' + FromJson = 'W' + } + @{ + TestInput = 88 + ToJson = '"X"' + FromJson = 'X' + } + @{ + TestInput = 89 + ToJson = '"Y"' + FromJson = 'Y' + } + @{ + TestInput = 90 + ToJson = '"Z"' + FromJson = 'Z' + } + @{ + TestInput = 91 + ToJson = '"["' + FromJson = '[' + } + @{ + TestInput = 92 + ToJson = '"\\"' + FromJson = '\' + } + @{ + TestInput = 93 + ToJson = '"]"' + FromJson = ']' + } + @{ + TestInput = 94 + ToJson = '"^"' + FromJson = '^' + } + @{ + TestInput = 95 + ToJson = '"_"' + FromJson = '_' + } + @{ + TestInput = 96 + ToJson = '"`"' + FromJson = '`' + } + @{ + TestInput = 97 + ToJson = '"a"' + FromJson = 'a' + } + @{ + TestInput = 98 + ToJson = '"b"' + FromJson = 'b' + } + @{ + TestInput = 99 + ToJson = '"c"' + FromJson = 'c' + } + @{ + TestInput = 100 + ToJson = '"d"' + FromJson = 'd' + } + @{ + TestInput = 101 + ToJson = '"e"' + FromJson = 'e' + } + @{ + TestInput = 102 + ToJson = '"f"' + FromJson = 'f' + } + @{ + TestInput = 103 + ToJson = '"g"' + FromJson = 'g' + } + @{ + TestInput = 104 + ToJson = '"h"' + FromJson = 'h' + } + @{ + TestInput = 105 + ToJson = '"i"' + FromJson = 'i' + } + @{ + TestInput = 106 + ToJson = '"j"' + FromJson = 'j' + } + @{ + TestInput = 107 + ToJson = '"k"' + FromJson = 'k' + } + @{ + TestInput = 108 + ToJson = '"l"' + FromJson = 'l' + } + @{ + TestInput = 109 + ToJson = '"m"' + FromJson = 'm' + } + @{ + TestInput = 110 + ToJson = '"n"' + FromJson = 'n' + } + @{ + TestInput = 111 + ToJson = '"o"' + FromJson = 'o' + } + @{ + TestInput = 112 + ToJson = '"p"' + FromJson = 'p' + } + @{ + TestInput = 113 + ToJson = '"q"' + FromJson = 'q' + } + @{ + TestInput = 114 + ToJson = '"r"' + FromJson = 'r' + } + @{ + TestInput = 115 + ToJson = '"s"' + FromJson = 's' + } + @{ + TestInput = 116 + ToJson = '"t"' + FromJson = 't' + } + @{ + TestInput = 117 + ToJson = '"u"' + FromJson = 'u' + } + @{ + TestInput = 118 + ToJson = '"v"' + FromJson = 'v' + } + @{ + TestInput = 119 + ToJson = '"w"' + FromJson = 'w' + } + @{ + TestInput = 120 + ToJson = '"x"' + FromJson = 'x' + } + @{ + TestInput = 121 + ToJson = '"y"' + FromJson = 'y' + } + @{ + TestInput = 122 + ToJson = '"z"' + FromJson = 'z' + } + @{ + TestInput = 123 + ToJson = '"{"' + FromJson = '{' + } + @{ + TestInput = 124 + ToJson = '"|"' + FromJson = '|' + } + @{ + TestInput = 125 + ToJson = '"}"' + FromJson = '}' + } + @{ + TestInput = 126 + ToJson = '"~"' + FromJson = '~' + } + @{ + TestInput = 127 + ToJson = '""' + FromJson = '' + } + ) + + function ValidateJsonSerializationForAsciiValues + { + param ($testCase) + + It "Validate 'ConvertTo-Json ([char]$($testCase.TestInput))', and 'ConvertTo-Json ([char]$($testCase.TestInput)) | ConvertFrom-Json'" { + + $result = @{ + ToJson = ConvertTo-Json ([char]$testCase.TestInput) + FromJson = ConvertTo-Json ([char]$testCase.TestInput) | ConvertFrom-Json + } + + if ($testCase.FromJson) + { + $result.FromJson | Should Be $testCase.FromJson + } + else + { + # There are two char for which the deserialized object must be compare to the serialized one via "Should Match" + # These values are [char]0 and [char]13. + $result.FromJson | Should Match $testCase.FromJson + } + $result.ToJson | Should Be $testCase.ToJson + } + } + + foreach ($testCase in $testCases) + { + ValidateJsonSerializationForAsciiValues $testCase + } + } + + Context "Validate Json serialization for types" { + + $testCases = @( + + ## Decimal types - Decimals are a 128-bit data type + @{ + TestInput = '[decimal]::MinValue' + FromJson = [decimal]::MinValue + ToJson = [decimal]::MinValue + } + @{ + TestInput = '[decimal]::MaxValue' + FromJson = [decimal]::MaxValue + ToJson = [decimal]::MaxValue + } + + # An sbyte is a signed 8-bit integer, and it ranges from -128 to 127. + # A byte is an unsigned 8-bit integer that ranges from 0 to 255 + @{ + TestInput = '[byte]::MinValue' + FromJson = [byte]::MinValue + ToJson = [byte]::MinValue + } + @{ + TestInput = '[byte]::MaxValue' + FromJson = [byte]::MaxValue + ToJson = [byte]::MaxValue + } + @{ + TestInput = '[sbyte]::MinValue' + FromJson = [sbyte]::MinValue + ToJson = [sbyte]::MinValue + } + @{ + TestInput = '[sbyte]::MaxValue' + FromJson = [sbyte]::MaxValue + ToJson = [sbyte]::MaxValue + } + @{ + TestInput = '[char]::MinValue' + FromJson = $null + ToJson = 'null' + } + @{ + TestInput = '[char]::MaxValue - 1' + FromJson = [char]::MaxValue - 1 + ToJson = [char]::MaxValue - 1 + } + @{ + TestInput = '[string]::Empty' + FromJson = [string]::Empty + ToJson = '""' + } + @{ + TestInput = '[string]"hello"' + FromJson = [string]"hello" + ToJson = '"hello"' + } + + # Int, int32, uint32, uint16, int16 + + # 32-bit signed integer + @{ + TestInput = '[int]::MaxValue' + FromJson = [int]::MaxValue + ToJson = [int]::MaxValue + } + @{ + TestInput = '[int]::MinValue' + FromJson = [int]::MinValue + ToJson = [int]::MinValue + } + @{ + TestInput = '[int32]::MaxValue' + FromJson = [int32]::MaxValue + ToJson = [int32]::MaxValue + } + @{ + TestInput = '[int32]::MinValue' + FromJson = [int32]::MinValue + ToJson = [int32]::MinValue + } + + # 32-bit unsigned integer + @{ + TestInput = '[uint32]::MaxValue' + FromJson = [uint32]::MaxValue + ToJson = [uint32]::MaxValue + } + @{ + TestInput = '[uint32]::MinValue' + FromJson = [uint32]::MinValue + ToJson = [uint32]::MinValue + } + + # 16-bit unsigned integer + @{ + TestInput = '[int16]::MinValue' + FromJson = [int16]::MinValue + ToJson = [int16]::MinValue + } + @{ + TestInput = '[uint16]::MaxValue' + FromJson = [uint16]::MaxValue + ToJson = [uint16]::MaxValue + } + + # 64-bit unsigned integer + @{ + TestInput = '[uint64]::MinValue' + FromJson = [uint64]::MinValue + ToJson = [uint64]::MinValue + } + @{ + TestInput = '[uint64]::MinValue' + FromJson = [uint64]::MinValue + ToJson = [uint64]::MinValue + } + + # 64 bit signed integer + @{ + TestInput = '[int64]::MaxValue' + FromJson = [int64]::MaxValue + ToJson = [int64]::MaxValue + } + @{ + TestInput = '[int64]::MinValue' + FromJson = [int64]::MinValue + ToJson = [int64]::MinValue + } + @{ + TestInput = '[long]::MaxValue' + FromJson = [long]::MaxValue + ToJson = [long]::MaxValue + } + @{ + TestInput = '[long]::MinValue' + FromJson = [long]::MinValue + ToJson = [long]::MinValue + } + + # Bool + @{ + TestInput = '[bool](1)' + FromJson = [bool](1) + ToJson = $true + } + @{ + TestInput = '[bool](0)' + FromJson = $false + ToJson = 'False' + } + + # Decimal + @{ + TestInput = '[decimal]::MaxValue' + FromJson = [decimal]::MaxValue + ToJson = [decimal]::MaxValue + } + @{ + TestInput = '[decimal]::MinValue' + FromJson = [decimal]::MinValue + ToJson = [decimal]::MinValue + } + + # Single + @{ + TestInput = '[single]::MaxValue' + FromJson = "3.40282347E+38" + ToJson = "3.40282347E+38" + } + @{ + TestInput = '[single]::MinValue' + FromJson = "-3.40282347E+38" + ToJson = "-3.40282347E+38" + } + + # Double + @{ + TestInput = '[double]::MaxValue' + FromJson = [double]::MaxValue + ToJson = [double]::MaxValue + } + @{ + TestInput = '[double]::MinValue' + FromJson = [double]::MinValue + ToJson = [double]::MinValue + } + ) + + function ValidateJsonSerialization + { + param ($testCase) + + It "Validate '$($testCase.TestInput) | ConvertTo-Json' and '$($testCase.TestInput) | ConvertTo-Json | ConvertFrom-Json'" { + + # The test case input is executed via invoke-expression. Then, we use this value as an input to ConvertTo-Json, + # and the result is saved into in the $result.ToJson variable. Lastly, this value is deserialized back using + # ConvertFrom-Json, and the value is saved to $result.FromJson for comparison. + + $expression = Invoke-Expression $testCase.TestInput + $result = @{ + ToJson = $expression | ConvertTo-Json + FromJson = $expression | ConvertTo-Json | ConvertFrom-Json + } + + $result.ToJson | Should Be $testCase.ToJson + $result.FromJson | Should Be $testCase.FromJson + } + } + + foreach ($testCase in $testCases) + { + ValidateJsonSerialization $testCase + } + } + + + Context "Validate Json Serialization for 'Get-CimClass' and 'Get-Command'" { + + function ValidateProperties + { + param ( + $serialized, + $expected, + $properties + ) + + # Validate that the two collections are the same size. + $expected.Count | Should Be $serialized.Count + + for ($index = 0; $index -lt $serialized.Count; $index++) + { + $serializedObject = $serialized[$index] + $expectedObject = $expected[$index] + foreach ($property in $properties) + { + # Write-Verbose "Validating $property" -Verbose + if ($property -eq "Qualifiers") + { + $serializedObject.$property.Count | Should Be $expectedObject.$property.Count + } + else + { + $serializedObject.$property | Should Be $expectedObject.$property + } + } + } + } + + It "Validate that CimClass Properties for win32_bios can be serialized using ConvertTo-Json and ConvertFrom-Json" { + + $class = Get-CimClass win32_bios + + $result = @{ + Expected = $class.CimClassProperties | ForEach-Object {$_} + SerializedViaJson = $class.CimClassProperties | ConvertTo-Json -Depth 10 | ConvertFrom-Json + } + + $propertiesToValidate = @("Name", "Flags", "Qualifiers", "ReferenceClassName") + + ValidateProperties -serialized $result.SerializedViaJson -expected $result.Expected -properties $propertiesToValidate + } + + It "Validate 'Get-Command Get-help' output with Json conversion" { + + $result = @{ + Expected = @(Get-Command Get-help) + SerializedViaJson = @(Get-Command Get-help | ConvertTo-Json | ConvertFrom-Json) + } + + $propertiesToValidate = @("Name", "Noun", "Verb") + ValidateProperties -serialized $result.SerializedViaJson -expected $result.Expected -properties $propertiesToValidate + } + + It "Validate 'Get-Command Get-Help, Get-command, Get-Member' output with Json conversion" { + + $result = @{ + Expected = @(Get-Command Get-Help, Get-Command, Get-Member) + SerializedViaJson = @(Get-Command Get-Help, Get-Command, Get-Member) | ConvertTo-Json | ConvertFrom-Json + } + + $propertiesToValidate = @("Name", "Source", "HelpFile") + ValidateProperties -serialized $result.SerializedViaJson -expected $result.Expected -properties $propertiesToValidate + } + + It "ConvertTo-JSON a dictionary of arrays" { + $a = 1..5 + $b = 6..10 + + $actual = @{'a'=$a;'b'=$b} | ConvertTo-Json + $expected = @' +{ + "a": [ + 1, + 2, + 3, + 4, + 5 + ], + "b": [ + 6, + 7, + 8, + 9, + 10 + ] +} +'@ + $actual | Should Be $expected + } + } +} + +Describe "Json Bug fixes" -Tags "RI", "P1" { + + function RunJsonTest + { + param ($testCase) + + It "$($testCase.Name)" { + + # Create a nested object + $start = 1 + $previous = @{ + Depth = $($testCase.NumberOfElements) + Next = $null + } + + ($($testCase.NumberOfElements)-1)..$start | foreach { + $current = @{ + Depth = $_ + Next = $previous + } + $previous = $current + } + + if ($testCase.ShouldThrow) + { + try + { + $previous | ConvertTo-Json -Depth $testCase.MaxDepth + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | Should Be $testCase.FullyQualifiedErrorId + } + } + else + { + $theError = $null + try + { + $previous | ConvertTo-Json -Depth $testCase.MaxDepth | ConvertFrom-Json + } + catch + { + $theError = $_ + } + $theError | Should Be $null + } + } + } + + $testCases = @( + @{ + Name = "ConvertTo-Json -Depth 101 throws MaximumAllowedDepthReached when the user specifies a depth greather than 100." + NumberOfElements = 10 + MaxDepth = 101 + FullyQualifiedErrorId = "ReachedMaximumDepthAllowed,Microsoft.PowerShell.Commands.ConvertToJsonCommand" + ShouldThrow = $true + } + @{ + Name = "ConvertTo-Json and ConvertFrom-Json work for any depth less than or equal to 100." + NumberOfElements = 100 + MaxDepth = 100 + ShouldThrow = $false + } + @{ + Name = "ConvertTo-Json and ConvertFrom-Json work for depth 100 with an object larger than 100." + NumberOfElements = 105 + MaxDepth = 100 + ShouldThrow = $false + } + ) + + foreach ($testCase in $testCases) + { + RunJsonTest $testCase + } +} \ No newline at end of file diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 new file mode 100644 index 000000000..0d0deff9a --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 @@ -0,0 +1,86 @@ +Describe "Tests for the Import-PowerShellDataFile cmdlet" -Tags 'P1', 'RI' { + + It "Validates error on a missing path" { + + $foundError = "" + try + { + Import-PowerShellDataFile -Path c:\SomeMissingDirectory -ErrorAction Stop + } + catch + { + $foundError = $_.FullyQualifiedErrorId + } + + $foundError | Should be "PathNotFound,Microsoft.PowerShell.Commands.ResolvePathCommand" + } + + It "Validates error on a directory" { + + $foundError = "" + try + { + Import-PowerShellDataFile ($env:SYSTEMDRIVE + '\') -ErrorAction Stop + } + catch + { + $foundError = $_.FullyQualifiedErrorId + } + + $foundError | Should be "CouldNotParseAsPowerShellDataFile,Import-PowerShellDataFile" + } + + It "Generates a good error on an insecure file" { + + $path = New-TemporaryFile + Set-Content $path '@{ Foo = Get-Process }' + + $foundError = "" + try + { + Import-PowerShellDataFile $path -ErrorAction Stop + } + catch + { + $foundError = $_.FullyQualifiedErrorId + } + finally + { + Remove-Item $path + } + + $foundError | Should be "InvalidOperationException,Import-PowerShellDataFile" + } + + It "Generates a good error on a file that isn't a PowerShell Data File (missing the hashtable root)" { + + $path = New-TemporaryFile + Set-Content $path '"Hello World"' + + $foundError = "" + try + { + Import-PowerShellDataFile $path -ErrorAction Stop + } + catch + { + $foundError = $_.FullyQualifiedErrorId + } + finally + { + Remove-Item $path + } + + $foundError | Should be "CouldNotParseAsPowerShellDataFileNoHashtableRoot,Import-PowerShellDataFile" + } + + It "Can parse a PowerShell Data File (detailed tests are in AST.SafeGetValue tests)" { + + $path = New-TemporaryFile + Set-Content $path '@{ "Hello" = "World" }' + + $result = Import-PowerShellDataFile $path -ErrorAction Stop + $result.Hello | Should be "World" + } + +} \ No newline at end of file diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/alias.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/alias.tests.ps1 new file mode 100644 index 000000000..8e1e94011 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/alias.tests.ps1 @@ -0,0 +1,160 @@ +Describe "Alias tests" -Tags "innerloop", "P1", "RI" { + + BeforeAll { + $testPath = Join-Path testdrive:\ ("testAlias\[.test") + New-Item -ItemType Directory -Path $testPath -Force | Out-Null + + class TestData + { + [string] $testName + [string] $testFile + [string] $expectedError + + TestData($name, $file, $error) + { + $this.testName = $name + $this.testFile = $file + $this.expectedError = $error + } + } + } + + Context "Export-Alias literal path" { + BeforeAll { + $csvFile = Join-Path $testPath "alias.csv" + $ps1File = Join-Path $testPath "alias.ps1" + + $testCases = @() + $testCases += [TestData]::new("CSV", $csvFile, [NullString]::Value) + $testCases += [TestData]::new("PS1", $ps1File, [NullString]::Value) + $testCases += [TestData]::new("Empty string", "", "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ExportAliasCommand") + $testCases += [TestData]::new("Null", [NullString]::Value, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportAliasCommand") + $testCases += [TestData]::new("Non filesystem provider", 'cert:\alias.ps1', "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ExportAliasCommand") + } + + $testCases | % { + + It "for $($_.testName)" { + + $test = $_ + try + { + Export-Alias -LiteralPath $test.testFile -ErrorAction SilentlyContinue + } + catch + { + $exportAliasError = $_ + } + + if($test.expectedError -eq $null) + { + Test-Path -LiteralPath $test.testFile | Should Be $true + } + else + { + $exportAliasError.FullyqualifiedErrorId | Should Be $test.expectedError + } + } + + AfterEach { + Remove-Item -LiteralPath $test.testFile -Force -ErrorAction SilentlyContinue + } + } + + It "when file exists with NoClobber" { + Export-Alias -LiteralPath $csvFile + + try + { + Export-Alias -LiteralPath $csvFile -NoClobber + } + catch + { + $exportAliasError = $_ + } + + $exportAliasError.FullyQualifiedErrorId | Should Be "NoClobber,Microsoft.PowerShell.Commands.ExportAliasCommand" + } + } + + Context "Export-All inside a literal path" { + BeforeEach { + Push-Location -LiteralPath $testPath + } + + It "with a CSV file" { + Export-Alias "alias.csv" + Test-Path -LiteralPath (Join-Path $testPath "alias.csv") | Should Be $true + } + + It "with NoClobber" { + $path = Export-Alias alias.csv + + try + { + Export-Alias alias.csv -NoClobber + } + catch + { + $exportAliasError = $_ + } + + $exportAliasError.FullyQualifiedErrorId | Should Be "NoClobber,Microsoft.PowerShell.Commands.ExportAliasCommand" + } + + AfterEach { + Pop-Location + } + } + + Context "Import-Alias literal path" { + + BeforeAll { + $csvFile = Join-Path $testPath "alias.csv" + $ps1File = Join-Path $testPath "alias.ps1" + + $testCases = @() + $testCases += [TestData]::new("Empty string", "", "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ImportAliasCommand") + $testCases += [TestData]::new("Null", [NullString]::Value, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ImportAliasCommand") + $testCases += [TestData]::new("Non filesystem provider", 'cert:\alias.ps1', "NotSupported,Microsoft.PowerShell.Commands.ImportAliasCommand") + } + + $testCases | % { + + It "for $($_.testName)" { + $test = $_ + + try + { + Import-Alias -LiteralPath $test.testFile -ErrorAction SilentlyContinue + } + catch + { + $exportAliasError = $_ + } + + $exportAliasError.FullyqualifiedErrorId | Should Be $test.expectedError + } + } + + It "can be done from a CSV file" { + + # alias file definition content + $aliasDefinition = @' + "myuh","update-help","","ReadOnly, AllScope" +'@ + + $aliasFile = Join-Path $testPath "alias.csv" + $aliasDefinition | Out-File -LiteralPath $aliasFile + + Import-Alias -LiteralPath $aliasFile + + # Verify that the alias was imported + $definedAlias = Get-Alias myuh + + $definedAlias | Should Not Be $null + $definedAlias.Name | Should Be "myuh" + $definedAlias.Definition | Should Be "update-help" + } + } +} \ No newline at end of file diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 new file mode 100644 index 000000000..957df5117 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 @@ -0,0 +1,187 @@ +Describe "CliXml test" -Tags "innerloop", "P1", "RI" { + + BeforeAll { + $testFilePath = Join-Path "testdrive:\" "testCliXml" + $subFilePath = Join-Path $testFilePath ".test" + + if(test-path $testFilePath) + { + Remove-Item $testFilePath -Force -Recurse + } + + # Create the test File and push the location into specified path + New-Item -Path $testFilePath -ItemType Directory | Out-Null + New-Item -Path $subFilePath -ItemType Directory | Out-Null + Push-Location $testFilePath + + class TestData + { + [string] $testName + [object] $inputObject + [string] $expectedError + [string] $testFile + + TestData($name, $file, $inputObj, $error) + { + $this.testName = $name + $this.inputObject = $inputObj + $this.expectedError = $error + $this.testFile = $file + } + } + } + + AfterAll { + Pop-Location + } + + Context "Export-CliXml" { + BeforeAll { + $gpsList = Get-Process powershell + $gps = $gpsList | Select-Object -First 1 + $filePath = Join-Path $subFilePath 'gps.xml' + + $testData = @() + $testData += [TestData]::new("with path as Null", [NullString]::Value, $gps, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportClixmlCommand") + $testData += [TestData]::new("with path as Empty string", "", $gps, "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ExportClixmlCommand") + $testData += [TestData]::new("with path as non filesystem provider", "cert:\", $gps, "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ExportClixmlCommand") + } + + AfterEach { + Remove-Item $filePath -Force -ErrorAction SilentlyContinue + } + + $testData | % { + + It "$($_.testName)" { + $test = $_ + + try + { + Export-Clixml -LiteralPath $test.testFile -InputObject $test.inputObject -Force + } + catch + { + $exportCliXmlError = $_ + } + + $exportCliXmlError.FullyQualifiedErrorId | Should Be $test.expectedError + } + } + + It "can be created with literal path" { + + $filePath = Join-Path $subFilePath 'gps.xml' + Export-Clixml -LiteralPath $filePath -InputObject ($gpsList | Select-Object -First 1) + + $filePath | Should Exist + + $fileContent = Get-Content $filePath + $isExisted = $false + + foreach($item in $fileContent) + { + foreach($gpsItem in $gpsList) + { + $checkId = $gpsItem.Id + if (($null -ne $(Select-String -InputObject $item -SimpleMatch $checkId)) -and ($null -ne $(Select-String -InputObject $item -SimpleMatch "Id"))) + { + $isExisted = $true + break; + } + } + } + + $isExisted | Should Be $true + } + + It "can be created with literal path using pipeline" { + + + $filePath = Join-Path $subFilePath 'gps.xml' + ($gpsList | Select-Object -First 1) | Export-Clixml -LiteralPath $filePath + + $filePath | Should Exist + + $fileContent = Get-Content $filePath + $isExisted = $false + + foreach($item in $fileContent) + { + foreach($gpsItem in $gpsList) + { + $checkId = $gpsItem.Id + if (($null -ne $(Select-String -InputObject $item -SimpleMatch $checkId)) -and ($null -ne $(Select-String -InputObject $item -SimpleMatch "Id"))) + { + $isExisted = $true + break; + } + } + } + + $isExisted | Should Be $true + } + } + + Context "Import-CliXML" { + BeforeAll { + $gpsList = Get-Process powershell + $gps = $gpsList | Select-Object -First 1 + $filePath = Join-Path $subFilePath 'gps.xml' + + $testData = @() + $testData += [TestData]::new("with path as Null", [NullString]::Value, $null, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ImportClixmlCommand") + $testData += [TestData]::new("with path as Empty string", "", $null, "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ImportClixmlCommand") + $testData += [TestData]::new("with path as non filesystem provider", "cert:\", $null, "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ImportClixmlCommand") + } + + $testData | % { + + It "$($_.testName)" { + $test = $_ + + try + { + Import-Clixml -LiteralPath $test.testFile + } + catch + { + $importCliXmlError = $_ + } + + $importCliXmlError.FullyQualifiedErrorId | Should Be $test.expectedError + } + } + + It "can import from a literal path" { + Export-Clixml -LiteralPath $filePath -InputObject $gps + $filePath | Should Exist + + $fileContent = Get-Content $filePath + $fileContent | Should Not Be $null + + $importedProcess = Import-Clixml $filePath + $gps.ProcessName | Should Be $importedProcess.ProcessName + $gps.Id | Should Be $importedProcess.Id + } + + It "can import from a literal path using pipeline" { + $gps | Export-Clixml -LiteralPath $filePath + $filePath | Should Exist + + $fileContent = Get-Content $filePath + $fileContent | Should Not Be $null + + $importedProcess = Import-Clixml $filePath + $gps.ProcessName | Should Be $importedProcess.ProcessName + $gps.Id | Should Be $importedProcess.Id + } + + It "test follow-up for WinBlue: 161470 - Export-CliXml errors in WhatIf scenarios" { + + $testPath = "testdrive:\Bug161470NonExistPath.txt" + Export-Clixml -Path $testPath -InputObject "string" -WhatIf + $testPath | Should Not Exist + } + } +} \ No newline at end of file diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 new file mode 100644 index 000000000..5480603b5 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 @@ -0,0 +1,80 @@ +Describe "Trace-Command" -tags "P1", "RI" { + + Context "Listner options" { + BeforeAll { + $logFile = New-Item "TestDrive:\traceCommandLog.txt" -Force + $actualLogFile = New-Item "TestDrive:\actualTraceCommandLog.txt" -Force + } + + AfterEach { + Remove-Item "TestDrive:\traceCommandLog.txt" -Force -ErrorAction SilentlyContinue + Remove-Item "TestDrive:\actualTraceCommandLog.txt" -Force -ErrorAction SilentlyContinue + } + + It "LogicalOperationStack works" { + $keyword = "Trace_Command_ListenerOption_LogicalOperationStack_Foo" + $stack = [System.Diagnostics.Trace]::CorrelationManager.LogicalOperationStack + $stack.Push($keyword) + + Trace-Command -Name * -Expression {echo Foo} -ListenerOption LogicalOperationStack -FilePath $logfile + + $log = Get-Content $logfile | Where-Object {$_ -like "*LogicalOperationStack=$keyword*"} + $log.Count | Should BeGreaterThan 0 + } + + It "Callstack works" { + Trace-Command -Name * -Expression {echo Foo} -ListenerOption Callstack -FilePath $logfile + $log = Get-Content $logfile | Where-Object {$_ -like "*Callstack= * System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)*"} + $log.Count | Should BeGreaterThan 0 + } + + It "Datetime works" { + $expectedDate = Trace-Command -Name * -Expression {Get-Date} -ListenerOption DateTime -FilePath $logfile + $log = Get-Content $logfile | Where-Object {$_ -like "*DateTime=*"} + $results = $log | ForEach-Object {[DateTime]::Parse($_.Split("=")[1])} + + ## allow a gap of 6 seconds. All traces should be finished within 6 seconds. + $allowedGap = [timespan](60 * 1000 * 1000) + $results | ForEach-Object { + $actualGap = $_ - $expectedDate; + if ($expectedDate -gt $_) + { + $actualGap = $expectedDate - $_; + } + + $allowedGap | Should BeGreaterThan $actualGap + } + } + + It "None options has no effect" { + Trace-Command -Name * -Expression {echo Foo} -ListenerOption None -FilePath $actualLogfile + Trace-Command -name * -Expression {echo Foo} -FilePath $logfile + + Compare-Object (Get-Content $actualLogfile) (Get-Content $logfile) | Should BeNullOrEmpty + } + + It "ThreadID works" { + Trace-Command -Name * -Expression {echo Foo} -ListenerOption ThreadId -FilePath $logfile + $log = Get-Content $logfile | Where-Object {$_ -like "*ThreadID=*"} + $results = $log | ForEach-Object {$_.Split("=")[1]} + + $results | % { $_ | Should Be ([threading.thread]::CurrentThread.ManagedThreadId) } + } + + It "Timestamp creates logs in ascending order" { + Trace-Command -Name * -Expression {echo Foo} -ListenerOption Timestamp -FilePath $logfile + $log = Get-Content $logfile | Where-Object {$_ -like "*Timestamp=*"} + $results = $log | ForEach-Object {$_.Split("=")[1]} + $sortedResults = $results | Sort-Object + $sortedResults | Should Be $results + } + + It "ProcessId logs current process Id" { + Trace-Command -Name * -Expression {echo Foo} -ListenerOption ProcessId -FilePath $logfile + $log = Get-Content $logfile | Where-Object {$_ -like "*ProcessID=*"} + $results = $log | ForEach-Object {$_.Split("=")[1]} + + $results | ForEach-Object { $_ | Should Be $pid } + } + } +} \ No newline at end of file diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1 new file mode 100644 index 000000000..02d54a42f --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1 @@ -0,0 +1,64 @@ +Describe "FormatData" -tags "P1", "RI" { + + Context "Export" { + It "can export all types" { + try + { + $expectAllFormat = Get-FormatData -typename * + $expectAllFormat | Export-FormatData -path $env:temp\allformat.ps1xml -IncludeScriptBlock + + $sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() + $sessionState.Formats.Clear() + $sessionState.Types.Clear() + + $runspace = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace($sessionState) + $runspace.Open() + + $runspace.CreatePipeline("Update-FormatData -AppendPath $env:temp\allformat.ps1xml").Invoke() + $actualAllFormat = $runspace.CreatePipeline("Get-FormatData -TypeName *").Invoke() + + $expectAllFormat.Count | Should Be $actualAllFormat.Count + Compare-Object $expectAllFormat $actualAllFormat | Should Be $null + $runspace.Close() + } + finally + { + Remove-Item -Path $env:temp\allformat.ps1xml -Force -ErrorAction SilentlyContinue + } + } + + It "works with literal path" { + $filename = 'TestDrive:\[formats.ps1xml' + Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename + (Test-Path -LiteralPath $filename) | Should Be $true + } + + It "should overwrite the destination file" { + $filename = 'TestDrive:\ExportFormatDataWithForce.ps1xml' + $unexpected = "SHOULD BE OVERWRITTEN" + $unexpected | Out-File -FilePath $filename -Force + $file = Get-Item $filename + $file.IsReadOnly = $true + Get-FormatData -TypeName * | Export-FormatData -Path $filename -Force + + $actual = @(Get-Content $filename)[0] + $actual | Should Not Be $unexpected + } + + It "should not overwrite the destination file with NoClobber" { + $filename = "TestDrive:\ExportFormatDataWithNoClobber.ps1xml" + Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename + + try + { + Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename -NoClobber + } + catch + { + $exportFormatError = $_ + } + + $exportFormatError.FullyQualifiedErrorId | Should Be 'NoClobber,Microsoft.PowerShell.Commands.ExportFormatDataCommand' + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/object.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/object.tests.ps1 new file mode 100644 index 000000000..496917101 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/object.tests.ps1 @@ -0,0 +1,100 @@ +Describe "Object cmdlets" -Tags 'innerloop', 'P1', 'RI' { + Context "Group-Object" { + It "AsHashtable returns a hashtable" { + $result = Get-Process | Group-Object -Property ProcessName -AsHashTable + $result["powershell"].Count | Should BeGreaterThan 0 + } + + It "AsString returns a string" { + $processes = Get-Process | Group-Object -Property ProcessName -AsHashTable -AsString + $result = $processes.Keys | ForEach-Object {$_.GetType()} + $result[0].Name | Should Be "String" + } + } + + Context "Tee-Object" { + It "with literal path" { + $path = "TestDrive:\[TeeObjectLiteralPathShouldWorkForSpecialFilename].txt" + Write-Output "Test" | Tee-Object -LiteralPath $path | Tee-Object -Variable TeeObjectLiteralPathShouldWorkForSpecialFilename + $TeeObjectLiteralPathShouldWorkForSpecialFilename | Should Be (Get-Content -LiteralPath $path) + } + } +} + +Describe "Object cmdlets" -Tags 'DRT' { + Context "Measure-Object" { + BeforeAll { + ## Powershell language prefers , as an array seperator without "". + ## If a number has comma in them it considers it to be the 1000 seperator like "1,000". + ## In de-DE language the comma is used as decimal point, but powershell still uses it as a 1000 seperator. + ## In case the number has a comma, it is ignored. So, "99,1" becomes 991. + ## To work around that behavior, we use ToString() on the expected answer and . for decimal in the input. + + $firstValue = "9995788.71" + $expectedFirstValue = $null + $null = [System.Management.Automation.LanguagePrimitives]::TryConvertTo($firstValue, [double], [cultureinfo]::InvariantCulture, [ref] $expectedFirstValue) + $firstObject = new-object psobject + $firstObject | Add-Member -NotePropertyName Header -NotePropertyValue $firstValue + + $secondValue = "15847577.7" + $expectedSecondValue = $null + $null = [System.Management.Automation.LanguagePrimitives]::TryConvertTo($secondValue, [double], [cultureinfo]::InvariantCulture, [ref] $expectedSecondValue) + $secondObject = new-object psobject + $secondObject | Add-Member -NotePropertyName Header -NotePropertyValue $secondValue + + $testCases = @( + @{ data = @("abc","ABC","Def"); min = "abc"; max = "Def"}, + @{ data = @([datetime]::Today, [datetime]::Today.AddDays(-1)); min = ([datetime]::Today.AddDays(-1)).ToString() ; max = [datetime]::Today.ToString() } + @{ data = @(1,2,3,"ABC"); min = 1; max = "ABC"}, + @{ data = @(4,2,3,"ABC",1); min = 1; max = "ABC"}, + @{ data = @(4,2,3,"ABC",1,"DEF"); min = 1; max = "DEF"}, + @{ data = @("111 Test","19"); min = "111 Test"; max = "19"}, + @{ data = @("19", "111 Test"); min = "111 Test"; max = "19"}, + @{ data = @("111 Test",19); min = "111 Test"; max = 19}, + @{ data = @(19, "111 Test"); min = "111 Test"; max = 19}, + @{ data = @(100,2,3, "A", 1); min = 1; max = "A"}, + @{ data = @(4,2,3, "ABC", 1, "DEF"); min = 1; max = "DEF"}, + @{ data = @("abc",[Datetime]::Today,"def"); min = [Datetime]::Today.ToString(); max = "def"} + ) + } + + It "can compare string representation for minimum" { + $minResult = $firstObject, $secondObject | Measure-Object Header -Minimum + $minResult.Minimum.ToString() | Should Be $expectedFirstValue.ToString() + } + + It "can compare string representation for maximum" { + $maxResult = $firstObject, $secondObject | Measure-Object Header -Maximum + $maxResult.Maximum.ToString() | Should Be $expectedSecondValue.ToString() + } + + It 'correctly find minimum of ()' -TestCases $testCases { + param($data, $min, $max) + + $output = $data | Measure-Object -Minimum + $output.Minimum.ToString() | Should Be $min + } + + It 'correctly find maximum of ()' -TestCases $testCases { + param($data, $min, $max) + + $output = $data | Measure-Object -Maximum + $output.Maximum.ToString() | Should Be $max + } + + It 'returns a GenericMeasureInfoObject' { + $gmi = 1,2,3 | measure-object -max -min + $gmi.GetType().FullName | Should Be 'Microsoft.PowerShell.Commands.GenericMeasureInfo' + } + + It 'should return correct error for non-numeric input' { + $gmi = "abc",[Datetime]::Now | measure -sum -max -ev err -ea silentlycontinue + $err | % { $_.FullyQualifiedErrorId | Should Be 'NonNumericInputObject,Microsoft.PowerShell.Commands.MeasureObjectCommand' } + } + + It 'should have the correct count' { + $gmi = "abc",[Datetime]::Now | measure -sum -max -ev err -ea silentlycontinue + $gmi.Count | Should Be 2 + } + } +} \ No newline at end of file diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 new file mode 100644 index 000000000..0282df288 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 @@ -0,0 +1,61 @@ +Describe "String cmdlets" -Tags 'innerloop', 'P1', 'RI' { + Context "Select-String" { + BeforeAll { + $fileName = New-Item 'TestDrive:\selectStr[ingLi]teralPath.txt' + "abc" | Out-File -LiteralPath $fileName.fullname + "bcd" | Out-File -LiteralPath $fileName.fullname -Append + "cde" | Out-File -LiteralPath $fileName.fullname -Append + + $fileNameWithDots = $fileName.FullName.Replace("\", "\.\") + + $tempFile = New-TemporaryFile + "abc" | Out-File -LiteralPath $tempFile.fullname + "bcd" | Out-File -LiteralPath $tempFile.fullname -Append + "cde" | Out-File -LiteralPath $tempFile.fullname -Append + $driveLetter = $tempFile.PSDrive.Name + $fileNameAsNetworkPath = "\\localhost\$driveLetter`$" + $tempFile.FullName.SubString(2) + + Push-Location "$fileName\.." + } + + AfterAll { + Remove-Item $tempFile -Force -ErrorAction SilentlyContinue + Pop-Location + } + + It "LiteralPath with relative path" { + (select-string -LiteralPath (Get-Item -LiteralPath $fileName).Name "b").count | Should Be 2 + } + + It "LiteralPath with absolute path" { + (select-string -LiteralPath $fileName "b").count | Should Be 2 + } + + It "LiteralPath with dots in path" { + (select-string -LiteralPath $fileNameWithDots "b").count | Should Be 2 + } + + It "Network path" { + (select-string -LiteralPath $fileNameAsNetworkPath "b").count | Should Be 2 + } + + It "throws error for non filesystem providers" { + select-string -literalPath cert:\currentuser\my "a" -ErrorAction SilentlyContinue -ErrorVariable selectStringError + $selectStringError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectStringCommand' + } + + It "throws parameter binding exception for invalid context" { + { select-string It $PSScriptRoot -Context -1,-1 } | Should Throw Context + } + + It "match object supports RelativePath method" { + $file = "Modules\Microsoft.PowerShell.Utility\Microsoft.PowerShell.Utility.psd1" + + $match = Select-String CmdletsToExport $pshome/$file + + $match.RelativePath($pshome) | Should Be $file + $match.RelativePath($pshome.ToLower()) | Should Be $file + $match.RelativePath($pshome.ToUpper()) | Should Be $file + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/typedata.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/typedata.tests.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..6e3288fc54aadf0c86a80cb1402bfe53c9b94207 GIT binary patch literal 10702 zcmeHNTT>%N6h6;Z`5&f2szAAId_-Jj$*x6NtO&S1tUdq<5H|@i35%%v*VXUqlaub5 zOwSCLtZ}ub!rV{yxqat5J^b}&Q`$0;GZ{)pPH~(_O^)5Qu{7mG#`q<;-;|j1a%<|UFIR8zPuo4|Lk(ks^FowuAS|A&W0VAdmD0q=*SyC&o|{> z+nM-kfRPf6%{&;pn5Fj;9BW=z@m@W6I*~65;xwM8M51)`SGUclcvmx8^KV_g1y249 zJ#*GrR%AXhKX388MXg~%o)s-BLj7LL6ZvWGm~!qiXGQAph+4EEpW{f+*PX9; z=DoCm*dUrQg6zpvSw(afX;z$-`TBDXc^24!|5%9>0e`?#V<7A-s#W)E4YN1T&SEvS zA421Hp@y0Xrity#^CKOLVLZhvoJo&kNL*@>o_&{{-CRA>`pxRK_j#Xw=tI%~cUS@VHf5a1TkJco z!V=#`*t8ZVcw^w6)484DoJ>G5a8_a%#j|YWd&p{GG%}RCa1vI1&9ydAw~H;tUd*?3 zXrN4t$hn1aX)$8nYoN>(EJchVw_qLYB2%`oDQ@fhRw6k$>pL4WoaJ+8;mZp1|KDWyF(0U!t#QdM#d*5Y8OIu(=UQFW6`yH0xqbwx`^4Bu|4g9$Q>Ig;Z|M=@{Fx z8Qk5LeMsxM)c|%_d^g01EZ@DGY|YY8-ZRYq3OW4-BQ4L&Z5g9)PI5c;7M}?3<;`$2 zN2|@LwWxzXqt1$g=E>~-F+BU(96bA*aGQ^3%Vd{%Hv9f!c{a`@LS*@$A#EVK7K0&$ zmBOznXm3Gu)n0?>+6S)ioGXl+`xx0>&czLN4L6lLadlLA&oS_u<1~R@9OWhUWAIlS zV+7{e$Fnz%uao0))K&caTH~SPGwg|a5$0~lQ^eV7653+6YUZ;w&n!$s_QZGPLdu%i zom0bE7H_P@*vYMYhq}X>)dBnK;GI^$`S)-Z?^eC-N3i-WtjqDpCqw<|0rrXH%(}j{ z2JElSI_ZnBrwL`7?~RYJviqm$-#ktq$Cf2o!isi+NYVZLu2w4C540{50W3;Pv%GyC&f6cz;7snWsNpp3KTwL?Ta)lDvg;5gw4(-Ru$EjhS zme#pwR}p3;{mf2oty11;M5&aps&locyerv(-? zlUzH;qscs=l{oZ(u3zv=&N;lvnB|drCBbUuwL?Wl5<5c1PBmW{Mwa)L@vl1h=#=HC zi{=H7%Vq;ZI>QJ<)wqANI_70nxwk`n3Vr?<{w>PIaNPWw^Iy$Bu0nGqfw;<*M_sd2 z*1+}76I|yir0;ZFm5|XQZ85XWW;b7Kv+9yvCAQH$u2n;@q6nW?wJGZS77gdh@rS(k z2Jx)5L%D>03HLtn^+(t4`Nf}E;rWiPw>3BZoa{Q5Glciqe{yY9zr`{(-e2#1KlYqPUw&W9;&xbt(vi)T zB=%5Ti9dzbmOr!v*8+HT=Ol=f7-PTnmJxB~MIKFD8zVKfls*by(*3XCCw@-zMWH)p>x*Z=?k literal 0 HcmV?d00001 diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 new file mode 100644 index 000000000..f2985945d --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 @@ -0,0 +1,62 @@ +Describe "XML cmdlets" -Tags 'P1', 'RI' { + Context "Select-XML" { + BeforeAll { + $fileName = New-Item -Path 'TestDrive:\testSelectXml.xml' + Push-Location "$fileName\.." + "" | out-file -LiteralPath $fileName + " " | out-file -LiteralPath $fileName -Append + "" | out-file -LiteralPath $fileName -Append + + $fileNameWithDots = $fileName.FullName.Replace("\", "\.\") + + $driveLetter = [string]($fileName.FullName)[0] + $fileNameAsNetworkPath = "\\localhost\$driveLetter`$" + $fileName.FullName.SubString(2) + + class TestData + { + [string] $testName + [hashtable] $parameters + + TestData($name, $parameters) + { + $this.testName = $name + $this.parameters = $parameters + } + } + + $testcases = @() + $testcases += [TestData]::new('literalpath with relative paths', @{LiteralPath = $fileName.Name; XPath = 'Root'}) + $testcases += [TestData]::new('literalpath with absolute paths', @{LiteralPath = $fileName.FullName; XPath = 'Root'}) + $testcases += [TestData]::new('literalpath with path with dots', @{LiteralPath = $fileNameWithDots; XPath = 'Root'}) + $testcases += [TestData]::new('literalpath with network path', @{LiteralPath = $fileNameAsNetworkPath; XPath = 'Root'}) + $testcases += [TestData]::new('path with relative paths', @{Path = $fileName.Name; XPath = 'Root'}) + $testcases += [TestData]::new('path with absolute paths', @{Path = $fileName.FullName; XPath = 'Root'}) + $testcases += [TestData]::new('path with path with dots', @{Path = $fileNameWithDots; XPath = 'Root'}) + $testcases += [TestData]::new('path with network path', @{Path = $fileNameAsNetworkPath; XPath = 'Root'}) + } + + AfterAll { + Remove-Item -LiteralPath $fileName -Force -ErrorAction SilentlyContinue + Pop-Location + } + + $testcases | % { + + $params = $_.parameters + + It $_.testName { + @(Select-XML @params).Count | Should Be 1 + } + } + + It "literalpath with non filesystem path" { + Select-XML -literalPath cert:\currentuser\my "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue + $selectXmlError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand' + } + + It "path with non filesystem path" { + Select-XML -Path cert:\currentuser\my "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue + $selectXmlError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand' + } + } +} \ No newline at end of file From 43eae99276910e389e15159533c33ea40a40ed52 Mon Sep 17 00:00:00 2001 From: PowerShell Team Date: Wed, 20 Jul 2016 15:12:50 -0700 Subject: [PATCH 09/25] remove scheduledjob cmdlet tests --- test/powershell/Modules/map.json | 1 - 1 file changed, 1 deletion(-) diff --git a/test/powershell/Modules/map.json b/test/powershell/Modules/map.json index 2c5b58594..29f7a8dd9 100644 --- a/test/powershell/Modules/map.json +++ b/test/powershell/Modules/map.json @@ -9,7 +9,6 @@ "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.GetCommand.ps1": "Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.ps1", "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.JsonTests.ps1": "Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.JsonTests.ps1", "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1": "Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.core.job.tests.ps1": "Microsoft.PowerShell.Core/core.job.tests.ps1", "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.History.Tests.ps1": "Microsoft.PowerShell.Core/History.Tests.ps1", "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Management.Copy.Item.Tests.ps1": "Microsoft.PowerShell.Management/Copy.Item.Tests.ps1", "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/pester.utility.alias.tests.ps1": "Microsoft.PowerShell.Utility/alias.tests.ps1", From 0261372baeb4e4a600162fca111f04ccbc5b559b Mon Sep 17 00:00:00 2001 From: PowerShell Team Date: Wed, 20 Jul 2016 15:14:15 -0700 Subject: [PATCH 10/25] remove scheduled job tests --- .../core.job.tests.ps1 | 42 ------------------- 1 file changed, 42 deletions(-) delete mode 100644 test/powershell/Modules/Microsoft.PowerShell.Core/core.job.tests.ps1 diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/core.job.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/core.job.tests.ps1 deleted file mode 100644 index 0853e9f36..000000000 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/core.job.tests.ps1 +++ /dev/null @@ -1,42 +0,0 @@ -Describe "Job cmdlets" -Tags 'innerloop', 'DRT' { - Context "Start-Job" { - It "should be able to load by definitionName and type" { - $jobname = "StartJobShouldBeAbleLoadByDefinitionNameAndType" - try - { - $scheduledjob = Get-ScheduledJob -Name $jobname -ErrorAction SilentlyContinue - - if (!$scheduledjob) - { - $scheduledjob = Register-ScheduledJob -Name $jobname -ScriptBlock {echo $args[0]} -ArgumentList ($jobname) - } - - $job = Start-Job -DefinitionName $jobname -Type "*ScheduledJob*" - $actual = $job | Wait-Job | Receive-Job - $actual | Should Be $jobname - } - finally - { - Remove-Job -Name $jobname -Force -ErrorAction SilentlyContinue - Unregister-ScheduledJob -Name $jobname -Force -ErrorAction SilentlyContinue - } - } - - It "no recurse should not return result from child jobs" { - $message = "StartJobNoRecurseShouldNotReturnTheResultsFromAnyChildJobs" - try - { - $job = Start-Job {echo $args[0]} -ArgumentList ($message) - $result = $job | Wait-Job | Receive-Job -NoRecurse - $result | Should BeNullOrEmpty - - $result = $job.ChildJobs | Receive-Job - $result | Should Be $message - } - finally - { - $job | Remove-Job -Force - } - } - } -} \ No newline at end of file From ce4303b8739f9c03606b56f0f7782d55a5fcca69 Mon Sep 17 00:00:00 2001 From: PowerShell Team Date: Wed, 20 Jul 2016 18:13:53 -0700 Subject: [PATCH 11/25] migrated tests run clean on all platforms (locally) --- .../Pester.Commands.Cmdlets.ArchiveTests.ps1 | 435 +++++++++--------- .../History.Tests.ps1 | 4 +- .../Pester.Commands.Cmdlets.GetCommand.ps1 | 27 +- .../Copy.Item.Tests.ps1 | 11 +- ...mands.Cmdlets.NoNewlineParameter.Tests.ps1 | 4 +- .../FormatHex.Tests.ps1 | 55 +-- .../ImportExportCSV.Delimiter.Tests.ps1 | 27 +- .../MiscCmdletUpdates.Tests.ps1 | 6 +- .../NewGuid.Tests.ps1 | 2 +- .../NewTemporaryFile.Tests.ps1 | 2 +- .../Pester.Commands.Cmdlets.JsonTests.ps1 | 29 +- .../PowerShellData.tests.ps1 | 8 +- .../alias.tests.ps1 | 4 +- .../clixml.tests.ps1 | 4 +- .../command.tests.ps1 | 30 +- .../formatdata.tests.ps1 | 8 +- .../object.tests.ps1 | 6 +- .../string.tests.ps1 | 10 +- .../typedata.tests.ps1 | Bin 10702 -> 10592 bytes .../xml.tests.ps1 | 18 +- 20 files changed, 369 insertions(+), 321 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.ArchiveTests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.ArchiveTests.ps1 index 387b0eb32..f4a5db6ff 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.ArchiveTests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.ArchiveTests.ps1 @@ -4,33 +4,40 @@ # used for validating Microsoft.PowerShell.Archive module. ############################################################################################> $script:TestSourceRoot = $PSScriptRoot -Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { +Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { + AfterAll { + $global:ProgressPreference = $_progressPreference + } BeforeAll { + # Write-Progress not supported yet on Core + $_progressPreference = $ProgressPreference + if ( $IsCore ) { $global:ProgressPreference = "SilentlyContinue" } + + Setup -d SourceDir + Setup -d SourceDir/ChildDir-1 + Setup -d SourceDir/ChildDir-2 + Setup -d SourceDir/ChildEmptyDir - New-Item $TestDrive\SourceDir -Type Directory | Out-Null - New-Item $TestDrive\SourceDir\ChildDir-1 -Type Directory | Out-Null - New-Item $TestDrive\SourceDir\ChildDir-2 -Type Directory | Out-Null - New-Item $TestDrive\SourceDir\ChildEmptyDir -Type Directory | Out-Null - $content = "Some Data" - $content | Out-File -FilePath $TestDrive\SourceDir\Sample-1.txt - $content | Out-File -FilePath $TestDrive\SourceDir\Sample-2.txt - $content | Out-File -FilePath $TestDrive\SourceDir\ChildDir-1\Sample-3.txt - $content | Out-File -FilePath $TestDrive\SourceDir\ChildDir-1\Sample-4.txt - $content | Out-File -FilePath $TestDrive\SourceDir\ChildDir-2\Sample-5.txt - $content | Out-File -FilePath $TestDrive\SourceDir\ChildDir-2\Sample-6.txt - - "Some Text" > $TestDrive\Sample.unzip - "Some Text" > $TestDrive\Sample.cab + $Files = ( [io.path]::Combine("SourceDir","Sample-1.txt")), ([io.path]::Combine("SourceDir","Sample-2.txt")), + ([io.path]::Combine("SourceDir","ChildDir-1","Sample-3.txt")), ([io.path]::Combine("SourceDir","ChildDir-1","Sample-4.txt")), + ([io.path]::Combine("SourceDir","ChildDir-2","Sample-5.txt")), ([io.path]::Combine("SourceDir","ChildDir-2","Sample-6.txt")) + + foreach($file in $files ) { + Setup -f $file -content $content + } + + Setup -f Sample.unzip -content "Some Text" + Setup -f Sample.cab -content "Some Text" $preCreatedArchivePath = Join-Path $script:TestSourceRoot "SamplePreCreatedArchive.archive" - Copy-Item $preCreatedArchivePath $TestDrive\SamplePreCreatedArchive.zip -Force + Copy-Item $preCreatedArchivePath $TestDrive/SamplePreCreatedArchive.zip -Force } function Add-CompressionAssemblies { Add-Type -AssemblyName System.IO.Compression - if ($psedition -eq "Core") + if (($psedition -eq "Core") -or $IsCore ) { Add-Type -AssemblyName System.IO.Compression.ZipFile } @@ -155,7 +162,7 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { Add-CompressionAssemblies try { - $destFile = "$TestDrive\ExpandedFile"+([System.Guid]::NewGuid().ToString())+".txt" + $destFile = "$TestDrive/ExpandedFile"+([System.Guid]::NewGuid().ToString())+".txt" $archiveFileStreamArgs = @($path, [System.IO.FileMode]::Open) $archiveFileStream = New-Object -TypeName System.IO.FileStream -ArgumentList $archiveFileStreamArgs @@ -223,8 +230,8 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { Context "Compress-Archive - Parameter validation test cases" { It "Validate errors from Compress-Archive with NULL & EMPTY values for Path, LiteralPath, DestinationPath, CompressionLevel parameters" { - $sourcePath = "$TestDrive\SourceDir" - $destinationPath = "$TestDrive\SampleSingleFile.zip" + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "$TestDrive/SampleSingleFile.zip" CompressArchivePathParameterSetValidator $null $destinationPath CompressArchivePathParameterSetValidator $sourcePath $null @@ -251,26 +258,30 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } It "Validate errors from Compress-Archive when invalid path (non-existing path / non-filesystem path) is supplied for Path or LiteralPath parameters" { - CompressArchiveInValidPathValidator "$TestDrive\InvalidPath" $TestDrive "$TestDrive\InvalidPath" "ArchiveCmdletPathNotFound,Compress-Archive" - CompressArchiveInValidPathValidator "HKLM:\SOFTWARE" $TestDrive "HKLM:\SOFTWARE" "PathNotFound,Compress-Archive" - CompressArchiveInValidPathValidator "$TestDrive" "$TestDrive\NonExistingDirectory\sample.zip" "$TestDrive\NonExistingDirectory\sample.zip" "ArchiveCmdletPathNotFound,Compress-Archive" + CompressArchiveInValidPathValidator "$TestDrive/InvalidPath" $TestDrive "$TestDrive/InvalidPath" "ArchiveCmdletPathNotFound,Compress-Archive" + if ( ! $IsCore ) { + CompressArchiveInValidPathValidator "HKLM:/SOFTWARE" $TestDrive "HKLM:/SOFTWARE" "PathNotFound,Compress-Archive" + } + CompressArchiveInValidPathValidator "$TestDrive" "$TestDrive/NonExistingDirectory/sample.zip" "$TestDrive/NonExistingDirectory/sample.zip" "ArchiveCmdletPathNotFound,Compress-Archive" - $path = @("$TestDrive", "$TestDrive\InvalidPath") - CompressArchiveInValidPathValidator $path $TestDrive "$TestDrive\InvalidPath" "ArchiveCmdletPathNotFound,Compress-Archive" + $path = @("$TestDrive", "$TestDrive/InvalidPath") + CompressArchiveInValidPathValidator $path $TestDrive "$TestDrive/InvalidPath" "ArchiveCmdletPathNotFound,Compress-Archive" - $path = @("$TestDrive", "HKLM:\SOFTWARE") - CompressArchiveInValidPathValidator $path $TestDrive "HKLM:\SOFTWARE" "PathNotFound,Compress-Archive" + if ( ! $IsCore ) { + $path = @("$TestDrive", "HKLM:/SOFTWARE") + CompressArchiveInValidPathValidator $path $TestDrive "HKLM:/SOFTWARE" "PathNotFound,Compress-Archive" + } - $invalidUnZipFileFormat = "$TestDrive\Sample.unzip" + $invalidUnZipFileFormat = "$TestDrive/Sample.unzip" CompressArchiveInValidArchiveFileExtensionValidator $TestDrive "$invalidUnZipFileFormat" ".unzip" - $invalidcabZipFileFormat = "$TestDrive\Sample.cab" + $invalidcabZipFileFormat = "$TestDrive/Sample.cab" CompressArchiveInValidArchiveFileExtensionValidator $TestDrive "$invalidcabZipFileFormat" ".cab" } It "Validate error from Compress-Archive when archive file already exists and -Update parameter is not specified" { - $sourcePath = "$TestDrive\SourceDir" - $destinationPath = "$TestDrive\ValidateErrorWhenUpdateNotSpecified.zip" + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "$TestDrive/ValidateErrorWhenUpdateNotSpecified.zip" try { @@ -286,9 +297,9 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { It "Validate error from Compress-Archive when duplicate paths are supplied as input to Path parameter" { $sourcePath = @( - "$TestDrive\SourceDir\Sample-1.txt", - "$TestDrive\SourceDir\Sample-1.txt") - $destinationPath = "$TestDrive\DuplicatePaths.zip" + "$TestDrive/SourceDir/Sample-1.txt", + "$TestDrive/SourceDir/Sample-1.txt") + $destinationPath = "$TestDrive/DuplicatePaths.zip" try { @@ -303,9 +314,9 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { It "Validate error from Compress-Archive when duplicate paths are supplied as input to LiteralPath parameter" { $sourcePath = @( - "$TestDrive\SourceDir\Sample-1.txt", - "$TestDrive\SourceDir\Sample-1.txt") - $destinationPath = "$TestDrive\DuplicatePaths.zip" + "$TestDrive/SourceDir/Sample-1.txt", + "$TestDrive/SourceDir/Sample-1.txt") + $destinationPath = "$TestDrive/DuplicatePaths.zip" try { @@ -317,20 +328,57 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { $_.FullyQualifiedErrorId | Should Be "DuplicatePathFound,Compress-Archive" } } + + It "Validate that relative path can be specified as Path parameter of Compress-Archive cmdlet" { + $sourcePath = "./SourceDir" + $destinationPath = "RelativePathForPathParameter.zip" + try { + push-location $TESTDRIVE + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + finally { + Pop-Location + } + } + It "Validate that relative path can be specified as LiteralPath parameter of Compress-Archive cmdlet" { + $sourcePath = "./SourceDir" + $destinationPath = "RelativePathForLiteralPathParameter.zip" + try { + push-location $TESTDRIVE + Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + finally { + Pop-Location + } + } + It "Validate that relative path can be specified as DestinationPath parameter of Compress-Archive cmdlet" { + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "./RelativePathForDestinationPathParameter.zip" + try { + push-location $TESTDRIVE + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + finally { + Pop-Location + } + } } Context "Compress-Archive - functional test cases" { It "Validate that a single file can be compressed using Compress-Archive cmdlet" { - $sourcePath = "$TestDrive\SourceDir\ChildDir-1\Sample-3.txt" - $destinationPath = "$TestDrive\SampleSingleFile.zip" + $sourcePath = [io.path]::Combine("$TestDrive","SourceDir","ChildDir-1","Sample-3.txt") + $destinationPath = [io.path]::Combine("$TestDrive","SampleSingleFile.zip") Compress-Archive -Path $sourcePath -DestinationPath $destinationPath $destinationPath | Should Exist } # This test requires a fix in PS5 to support reading paths with square bracket It "Validate that Compress-Archive cmdlet can accept LiteralPath parameter with Special Characters" -skip:($PSVersionTable.psversion -lt "5.0") { - $sourcePath = "$TestDrive\SourceDir\ChildDir-1\Sample[]File.txt" + $sourcePath = "$TestDrive/SourceDir/ChildDir-1/Sample[]File.txt" "Some Random Content" | Out-File -LiteralPath $sourcePath - $destinationPath = "$TestDrive\SampleSingleFileWithSpecialCharacters.zip" + $destinationPath = "$TestDrive/SampleSingleFileWithSpecialCharacters.zip" try { Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath @@ -343,12 +391,12 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } It "Validate that Compress-Archive cmdlet errors out when DestinationPath resolves to multiple locations" { - New-Item $TestDrive\SampleDir\Child-1 -Type Directory -Force | Out-Null - New-Item $TestDrive\SampleDir\Child-2 -Type Directory -Force | Out-Null - New-Item $TestDrive\SampleDir\Test.txt -Type File -Force | Out-Null + New-Item $TestDrive/SampleDir/Child-1 -Type Directory -Force | Out-Null + New-Item $TestDrive/SampleDir/Child-2 -Type Directory -Force | Out-Null + New-Item $TestDrive/SampleDir/Test.txt -Type File -Force | Out-Null - $destinationPath = "$TestDrive\SampleDir\Child-*\SampleChidArchive.zip" - $sourcePath = "$TestDrive\SampleDir\Test.txt" + $destinationPath = "$TestDrive/SampleDir/Child-*/SampleChidArchive.zip" + $sourcePath = "$TestDrive/SampleDir/Test.txt" try { Compress-Archive -Path $sourcePath -DestinationPath $destinationPath @@ -360,16 +408,16 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } finally { - Remove-Item -LiteralPath $TestDrive\SampleDir -Force -Recurse + Remove-Item -LiteralPath $TestDrive/SampleDir -Force -Recurse } } It "Validate that Compress-Archive cmdlet works when DestinationPath has wild card pattern and resolves to a single valid path" { - New-Item $TestDrive\SampleDir\Child-1 -Type Directory -Force | Out-Null - New-Item $TestDrive\SampleDir\Test.txt -Type File -Force | Out-Null + New-Item $TestDrive/SampleDir/Child-1 -Type Directory -Force | Out-Null + New-Item $TestDrive/SampleDir/Test.txt -Type File -Force | Out-Null - $destinationPath = "$TestDrive\SampleDir\Child-*\SampleChidArchive.zip" - $sourcePath = "$TestDrive\SampleDir\Test.txt" + $destinationPath = "$TestDrive/SampleDir/Child-*/SampleChidArchive.zip" + $sourcePath = "$TestDrive/SampleDir/Test.txt" try { Compress-Archive -Path $sourcePath -DestinationPath $destinationPath @@ -377,15 +425,15 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } finally { - Remove-Item -LiteralPath $TestDrive\SampleDir -Force -Recurse + Remove-Item -LiteralPath $TestDrive/SampleDir -Force -Recurse } } # This test requires a fix in PS5 to support reading paths with square bracket It "Validate that Compress-Archive cmdlet can accept LiteralPath parameter for a directory with Special Characters in the directory name" -skip:($PSVersionTable.psversion -lt "5.0") { - $sourcePath = "$TestDrive\Source[]Dir\ChildDir[]-1" + $sourcePath = "$TestDrive/Source[]Dir/ChildDir[]-1" New-Item $sourcePath -Type Directory | Out-Null - "Some Random Content" | Out-File -LiteralPath "$sourcePath\Sample[]File.txt" - $destinationPath = "$TestDrive\SampleDirWithSpecialCharacters.zip" + "Some Random Content" | Out-File -LiteralPath "$sourcePath/Sample[]File.txt" + $destinationPath = "$TestDrive/SampleDirWithSpecialCharacters.zip" try { Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath @@ -397,8 +445,8 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } } It "Validate that Compress-Archive cmdlet can accept DestinationPath parameter with Special Characters" { - $sourcePath = "$TestDrive\SourceDir\ChildDir-1\Sample-3.txt" - $destinationPath = "$TestDrive\Sample[]SingleFile.zip" + $sourcePath = "$TestDrive/SourceDir/ChildDir-1/Sample-3.txt" + $destinationPath = "$TestDrive/Sample[]SingleFile.zip" try { Compress-Archive -Path $sourcePath -DestinationPath $destinationPath @@ -409,11 +457,11 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { Remove-Item -LiteralPath $destinationPath -Force } } - It "Validate that Source Path can be at SystemDrive location" { - $sourcePath = "$env:SystemDrive\SourceDir" - $destinationPath = "$TestDrive\SampleFromSystemDrive.zip" + It "Validate that Source Path can be at SystemDrive location" -skip:($IsCore) { + $sourcePath = "$env:SystemDrive/SourceDir" + $destinationPath = "$TestDrive/SampleFromSystemDrive.zip" New-Item $sourcePath -Type Directory | Out-Null - "Some Data" | Out-File -FilePath $sourcePath\SampleSourceFileForArchive.txt + "Some Data" | Out-File -FilePath $sourcePath/SampleSourceFileForArchive.txt try { Compress-Archive -Path $sourcePath -DestinationPath $destinationPath @@ -421,145 +469,104 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } finally { - del "$sourcePath" -Force -Recurse -ErrorAction SilentlyContinue + remove-item "$sourcePath" -Force -Recurse -ErrorAction SilentlyContinue } } It "Validate that multiple files can be compressed using Compress-Archive cmdlet" { $sourcePath = @( - "$TestDrive\SourceDir\ChildDir-1\Sample-3.txt", - "$TestDrive\SourceDir\ChildDir-1\Sample-4.txt", - "$TestDrive\SourceDir\ChildDir-2\Sample-5.txt", - "$TestDrive\SourceDir\ChildDir-2\Sample-6.txt") - $destinationPath = "$TestDrive\SampleMultipleFiles.zip" + "$TestDrive/SourceDir/ChildDir-1/Sample-3.txt", + "$TestDrive/SourceDir/ChildDir-1/Sample-4.txt", + "$TestDrive/SourceDir/ChildDir-2/Sample-5.txt", + "$TestDrive/SourceDir/ChildDir-2/Sample-6.txt") + $destinationPath = "$TestDrive/SampleMultipleFiles.zip" Compress-Archive -Path $sourcePath -DestinationPath $destinationPath Test-Path $destinationPath | Should Be $true } It "Validate that multiple files and directories can be compressed using Compress-Archive cmdlet" { $sourcePath = @( - "$TestDrive\SourceDir\Sample-1.txt", - "$TestDrive\SourceDir\Sample-2.txt", - "$TestDrive\SourceDir\ChildDir-1", - "$TestDrive\SourceDir\ChildDir-2") - $destinationPath = "$TestDrive\SampleMultipleFilesAndDirs.zip" + "$TestDrive/SourceDir/Sample-1.txt", + "$TestDrive/SourceDir/Sample-2.txt", + "$TestDrive/SourceDir/ChildDir-1", + "$TestDrive/SourceDir/ChildDir-2") + $destinationPath = "$TestDrive/SampleMultipleFilesAndDirs.zip" Compress-Archive -Path $sourcePath -DestinationPath $destinationPath Test-Path $destinationPath | Should Be $true } It "Validate that a single directory can be compressed using Compress-Archive cmdlet" { - $sourcePath = @("$TestDrive\SourceDir\ChildDir-1") - $destinationPath = "$TestDrive\SampleSingleDir.zip" + $sourcePath = @("$TestDrive/SourceDir/ChildDir-1") + $destinationPath = "$TestDrive/SampleSingleDir.zip" Compress-Archive -Path $sourcePath -DestinationPath $destinationPath Test-Path $destinationPath | Should Be $true } It "Validate that a single directory with multiple files and subdirectories can be compressed using Compress-Archive cmdlet" { - $sourcePath = @("$TestDrive\SourceDir") - $destinationPath = "$TestDrive\SampleSubTree.zip" + $sourcePath = @("$TestDrive/SourceDir") + $destinationPath = "$TestDrive/SampleSubTree.zip" Compress-Archive -Path $sourcePath -DestinationPath $destinationPath Test-Path $destinationPath | Should Be $true } It "Validate that a single directory & multiple files can be compressed using Compress-Archive cmdlet" { $sourcePath = @( - "$TestDrive\SourceDir\ChildDir-1", - "$TestDrive\SourceDir\Sample-1.txt", - "$TestDrive\SourceDir\Sample-2.txt") - $destinationPath = "$TestDrive\SampleMultipleFilesAndSingleDir.zip" + "$TestDrive/SourceDir/ChildDir-1", + "$TestDrive/SourceDir/Sample-1.txt", + "$TestDrive/SourceDir/Sample-2.txt") + $destinationPath = "$TestDrive/SampleMultipleFilesAndSingleDir.zip" Compress-Archive -Path $sourcePath -DestinationPath $destinationPath Test-Path $destinationPath | Should Be $true } It "Validate that if .zip extension is not supplied as input to DestinationPath parameter, then .zip extension is appended" { - $sourcePath = @("$TestDrive\SourceDir") - $destinationPath = "$TestDrive\SampleNoExtension.zip" - $destinationWithoutExtensionPath = "$TestDrive\SampleNoExtension" + $sourcePath = @("$TestDrive/SourceDir") + $destinationPath = "$TestDrive/SampleNoExtension.zip" + $destinationWithoutExtensionPath = "$TestDrive/SampleNoExtension" Compress-Archive -Path $sourcePath -DestinationPath $destinationWithoutExtensionPath Test-Path $destinationPath | Should Be $true } - It "Validate that relative path can be specified as Path parameter of Compress-Archive cmdlet" { - $sourcePath = ".\SourceDir" - $destinationPath = "RelativePathForPathParameter.zip" - try - { - Push-Location $TestDrive - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - finally - { - Pop-Location - } - } - It "Validate that relative path can be specified as LiteralPath parameter of Compress-Archive cmdlet" { - $sourcePath = ".\SourceDir" - $destinationPath = "RelativePathForLiteralPathParameter.zip" - try - { - Push-Location $TestDrive - Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - finally - { - Pop-Location - } - } - It "Validate that relative path can be specified as DestinationPath parameter of Compress-Archive cmdlet" { - $sourcePath = "$TestDrive\SourceDir" - $destinationPath = ".\RelativePathForDestinationPathParameter.zip" - try - { - Push-Location $TestDrive - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - finally - { - Pop-Location - } - } + It "Validate that -Update parameter makes Compress-Archive to not throw an error if archive file already exists" { - $sourcePath = @("$TestDrive\SourceDir") - $destinationPath = "$TestDrive\SampleUpdateTest.zip" + $sourcePath = @("$TestDrive/SourceDir") + $destinationPath = "$TestDrive/SampleUpdateTest.zip" Compress-Archive -Path $sourcePath -DestinationPath $destinationPath Test-Path $destinationPath | Should Be $true Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update Test-Path $destinationPath | Should Be $true } It "Validate -Update parameter by adding a new file to an existing archive file" { - $sourcePath = @("$TestDrive\SourceDir\ChildDir-1") - $destinationPath = "$TestDrive\SampleUpdateAdd1File.zip" + $sourcePath = @("$TestDrive/SourceDir/ChildDir-1") + $destinationPath = "$TestDrive/SampleUpdateAdd1File.zip" Compress-Archive -Path $sourcePath -DestinationPath $destinationPath Test-Path $destinationPath | Should Be $true - New-Item $TestDrive\SourceDir\ChildDir-1\Sample-AddedNewFile.txt -Type File | Out-Null + New-Item $TestDrive/SourceDir/ChildDir-1/Sample-AddedNewFile.txt -Type File | Out-Null Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update Test-Path $destinationPath | Should Be $true Validate-ArchiveEntryCount -path $destinationPath -expectedEntryCount 3 } It "Validate that all CompressionLevel values can be used with Compress-Archive cmdlet" { - $sourcePath = "$TestDrive\SourceDir\Sample-1.txt" + $sourcePath = "$TestDrive/SourceDir/Sample-1.txt" - $destinationPath = "$TestDrive\FastestCompressionLevel.zip" + $destinationPath = "$TestDrive/FastestCompressionLevel.zip" Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel Fastest Test-Path $destinationPath | Should Be $true - $destinationPath = "$TestDrive\OptimalCompressionLevel.zip" + $destinationPath = "$TestDrive/OptimalCompressionLevel.zip" Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel Optimal Test-Path $destinationPath | Should Be $true - $destinationPath = "$TestDrive\NoCompressionCompressionLevel.zip" + $destinationPath = "$TestDrive/NoCompressionCompressionLevel.zip" Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel NoCompression Test-Path $destinationPath | Should Be $true } It "Validate that -Update parameter is modifying a file that already exists in the archive file" { - $filePath = "$TestDrive\SourceDir\ChildDir-1\Sample-3.txt" + $filePath = "$TestDrive/SourceDir/ChildDir-1/Sample-3.txt" $initialContent = "Initial Content" $modifiedContent = "Modified Content" $initialContent | Set-Content $filePath - $sourcePath = "$TestDrive\SourceDir" - $destinationPath = "$TestDrive\UpdatingModifiedFile.zip" + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "$TestDrive/UpdatingModifiedFile.zip" Compress-Archive -Path $sourcePath -DestinationPath $destinationPath Test-Path $destinationPath | Should Be $True @@ -569,28 +576,28 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update Test-Path $destinationPath | Should Be $True - ArchiveFileEntryContentValidator "$destinationPath" "SourceDir\ChildDir-1\Sample-3.txt" $modifiedContent + ArchiveFileEntryContentValidator "$destinationPath" ([io.path]::Combine("SourceDir","ChildDir-1","Sample-3.txt")) $modifiedContent } It "Validate Compress-Archive cmdlet in pipleline scenario" { - $destinationPath = "$TestDrive\CompressArchiveFromPipeline.zip" + $destinationPath = "$TestDrive/CompressArchiveFromPipeline.zip" # Piping a single file path to Compress-Archive - dir -Path $TestDrive\SourceDir\Sample-1.txt | Compress-Archive -DestinationPath $destinationPath + dir -Path $TestDrive/SourceDir/Sample-1.txt | Compress-Archive -DestinationPath $destinationPath Test-Path $destinationPath | Should Be $True # Piping a string directory path to Compress-Archive - "$TestDrive\SourceDir\ChildDir-2" | Compress-Archive -DestinationPath $destinationPath -Update + "$TestDrive/SourceDir/ChildDir-2" | Compress-Archive -DestinationPath $destinationPath -Update Test-Path $destinationPath | Should Be $True # Piping the output of Get-ChildItem to Compress-Archive - dir "$TestDrive\SourceDir" -Recurse | Compress-Archive -DestinationPath $destinationPath -Update + dir "$TestDrive/SourceDir" -Recurse | Compress-Archive -DestinationPath $destinationPath -Update Test-Path $destinationPath | Should Be $True } It "Validate that Compress-Archive works on ReadOnly files" { - $sourcePath = "$TestDrive\ReadOnlyFile.txt" - $destinationPath = "$TestDrive\TestForReadOnlyFile.zip" + $sourcePath = "$TestDrive/ReadOnlyFile.txt" + $destinationPath = "$TestDrive/TestForReadOnlyFile.zip" "Some Content" | Out-File -FilePath $sourcePath $createdItem = Get-Item $sourcePath @@ -601,8 +608,8 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } It "Validate that Compress-Archive generates Verbose messages" { - $sourcePath = "$TestDrive\SourceDir" - $destinationPath = "$TestDrive\Compress-Archive generates VerboseMessages.zip" + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "$TestDrive/Compress-Archive generates VerboseMessages.zip" try { @@ -625,8 +632,8 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { Context "Expand-Archive - Parameter validation test cases" { It "Validate non existing archive -Path trows expected error message" { - $sourcePath = "$TestDrive\SourceDir" - $destinationPath = "$TestDrive\ExpandedArchive" + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "$TestDrive/ExpandedArchive" try { Expand-Archive -Path $sourcePath -DestinationPath $destinationPath @@ -639,48 +646,53 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } It "Validate errors from Expand-Archive with NULL & EMPTY values for Path, LiteralPath, DestinationPath parameters" { - ExpandArchiveInvalidParameterValidator $false $null "$TestDrive\SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $false $null "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" ExpandArchiveInvalidParameterValidator $false $null $null "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $false "$TestDrive\SourceDir" $null "ParameterArgumentTransformationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $false "" "$TestDrive\SourceDir" "ParameterArgumentTransformationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $false "$TestDrive\SourceDir" "" "ParameterArgumentTransformationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $false "$TestDrive/SourceDir" $null "ParameterArgumentTransformationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $false "" "$TestDrive/SourceDir" "ParameterArgumentTransformationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $false "$TestDrive/SourceDir" "" "ParameterArgumentTransformationError,Expand-Archive" ExpandArchiveInvalidParameterValidator $false "" "" "ParameterArgumentTransformationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true $null "$TestDrive\SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true $null "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" ExpandArchiveInvalidParameterValidator $true $null $null "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "$TestDrive\SourceDir" $null "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "" "$TestDrive\SourceDir" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "$TestDrive\SourceDir" "" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" $null "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "" "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" "" "ParameterArgumentValidationError,Expand-Archive" ExpandArchiveInvalidParameterValidator $true "" "" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true $null "$TestDrive\SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true $null "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" ExpandArchiveInvalidParameterValidator $true $null $null "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "$TestDrive\SourceDir" $null "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "" "$TestDrive\SourceDir" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "$TestDrive\SourceDir" "" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" $null "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "" "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" "" "ParameterArgumentValidationError,Expand-Archive" ExpandArchiveInvalidParameterValidator $true "" "" "ParameterArgumentValidationError,Expand-Archive" } It "Validate errors from Expand-Archive when invalid path (non-existing path / non-filesystem path) is supplied for Path or LiteralPath parameters" { - try { Expand-Archive -Path "$TestDrive\NonExistingArchive" -DestinationPath "$TestDrive\SourceDir"; throw "Expand-Archive did NOT throw expected error" } + try { Expand-Archive -Path "$TestDrive/NonExistingArchive" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } catch { $_.FullyQualifiedErrorId | Should Be "ArchiveCmdletPathNotFound,Expand-Archive" } - try { Expand-Archive -Path "HKLM:\SOFTWARE" -DestinationPath "$TestDrive\SourceDir"; throw "Expand-Archive did NOT throw expected error" } - catch { $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" } + if ( ! $IsCore ) { + try { Expand-Archive -Path "HKLM:/SOFTWARE" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" } + } - try { Expand-Archive -LiteralPath "$TestDrive\NonExistingArchive" -DestinationPath "$TestDrive\SourceDir"; throw "Expand-Archive did NOT throw expected error" } + try { Expand-Archive -LiteralPath "$TestDrive/NonExistingArchive" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } catch { $_.FullyQualifiedErrorId | Should Be "ArchiveCmdletPathNotFound,Expand-Archive" } - try { Expand-Archive -LiteralPath "HKLM:\SOFTWARE" -DestinationPath "$TestDrive\SourceDir"; throw "Expand-Archive did NOT throw expected error" } - catch { $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" } + if ( ! $IsCore ) { + try { Expand-Archive -LiteralPath "HKLM:/SOFTWARE" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" } + } } It "Validate error from Expand-Archive when invalid path (non-existing path / non-filesystem path) is supplied for DestinationPath parameter" { - $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" - $destinationPath = "HKLM:\SOFTWARE" + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + # $destinationPath = "HKLM:/SOFTWARE" + $destinationPath = "Variable:/" try { Expand-Archive -Path $sourcePath -DestinationPath $destinationPath; throw "Expand-Archive did NOT throw expected error" } catch { $_.FullyQualifiedErrorId | Should Be "InvalidDirectoryPath,Expand-Archive" } @@ -688,14 +700,13 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } Context "Expand-Archive - functional test cases" { - It "Validate basic Expand-Archive scenario" { - $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" $content = "Some Data" - $destinationPath = "$TestDrive\DestDirForBasicExpand" + $destinationPath = "$TestDrive/DestDirForBasicExpand" $files = @("Sample-1.txt", "Sample-2.txt") - # The files in "$TestDrive\SamplePreCreatedArchive.zip" are precreated. + # The files in "$TestDrive/SamplePreCreatedArchive.zip" are precreated. $fileCreationTimeStamp = Get-Date -Year 2014 -Month 6 -Day 13 -Hour 15 -Minute 50 -Second 20 -Millisecond 0 Expand-Archive -Path $sourcePath -DestinationPath $destinationPath @@ -712,11 +723,13 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } } It "Validate that Expand-Archive cmdlet errors out when DestinationPath resolves to multiple locations" { - New-Item $TestDrive\SampleDir\Child-1 -Type Directory -Force | Out-Null - New-Item $TestDrive\SampleDir\Child-2 -Type Directory -Force | Out-Null + $testbasename = "TargetDir" + setup -d "$testbasename" + setup -d "$testbasename/Child-1" + setup -d "$testbasename/Child-2" - $destinationPath = "$TestDrive\SampleDir\Child-*" - $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" + $destinationPath = [io.path]::Combine("$TestDrive","$testbasename","Child-*") + $sourcePath = join-path "$TestDrive" "SamplePreCreatedArchive.zip" try { Expand-Archive -Path $sourcePath -DestinationPath $destinationPath @@ -728,14 +741,16 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } finally { - Remove-Item -LiteralPath $TestDrive\SampleDir -Force -Recurse + Remove-Item -LiteralPath "$TestDrive/$testbasename" -Force -Recurse } } It "Validate that Expand-Archive cmdlet works when DestinationPath resolves has wild card pattern and resolves to a single valid path" { - New-Item $TestDrive\SampleDir\Child-1 -Type Directory -Force | Out-Null + $testbasename = "TargetDir" + setup -d "$testbasename" + setup -d "$testbasename/Child-1" - $destinationPath = "$TestDrive\SampleDir\Child-*" - $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" + $destinationPath = [io.path]::Combine("$TestDrive","$testbasename","Child-*") + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" try { Expand-Archive -Path $sourcePath -DestinationPath $destinationPath @@ -744,16 +759,16 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } finally { - Remove-Item -LiteralPath $TestDrive\SampleDir -Force -Recurse + Remove-Item -LiteralPath "$TestDrive/$testbasename" -Force -Recurse } } It "Validate Expand-Archive scenario where DestinationPath has Special Characters" { - $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" $content = "Some Data" - $destinationPath = "$TestDrive\DestDir[]Expand" + $destinationPath = "$TestDrive/DestDir[]Expand" $files = @("Sample-1.txt", "Sample-2.txt") - # The files in "$TestDrive\SamplePreCreatedArchive.zip" are precreated. + # The files in "$TestDrive/SamplePreCreatedArchive.zip" are precreated. $fileCreationTimeStamp = Get-Date -Year 2014 -Month 6 -Day 13 -Hour 15 -Minute 50 -Second 20 -Millisecond 0 Expand-Archive -Path $sourcePath -DestinationPath $destinationPath @@ -770,8 +785,8 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } } It "Invoke Expand-Archive with relative path in Path parameter and -Force parameter" { - $sourcePath = ".\SamplePreCreatedArchive.zip" - $destinationPath = "$TestDrive\SomeOtherNonExistingDir\Path" + $sourcePath = "./SamplePreCreatedArchive.zip" + $destinationPath = "$TestDrive/SomeOtherNonExistingDir/Path" try { Push-Location $TestDrive @@ -787,8 +802,8 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } It "Invoke Expand-Archive with relative path in LiteralPath parameter and -Force parameter" { - $sourcePath = ".\SamplePreCreatedArchive.zip" - $destinationPath = "$TestDrive\SomeOtherNonExistingDir\LiteralPath" + $sourcePath = "./SamplePreCreatedArchive.zip" + $destinationPath = "$TestDrive/SomeOtherNonExistingDir/LiteralPath" try { Push-Location $TestDrive @@ -804,8 +819,8 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } It "Invoke Expand-Archive with non-existing relative directory in DestinationPath parameter and -Force parameter" { - $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" - $destinationPath = ".\SomeOtherNonExistingDir\DestinationPath" + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $destinationPath = "./SomeOtherNonExistingDir/DestinationPath" try { Push-Location $TestDrive @@ -821,8 +836,8 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } It "Invoke Expand-Archive with unsupported archive format" { - $sourcePath = "$TestDrive\Sample.cab" - $destinationPath = "$TestDrive\UnsupportedArchiveFormatDir" + $sourcePath = "$TestDrive/Sample.cab" + $destinationPath = "$TestDrive/UnsupportedArchiveFormatDir" try { Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Force @@ -835,9 +850,9 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } It "Invoke Expand-Archive with archive file containing multiple files, directories with subdirectories and empty directories" { - $sourcePath = "$TestDrive\SourceDir" - $archivePath = "$TestDrive\FileAndDirTreeForExpand.zip" - $destinationPath = "$TestDrive\FileAndDirTree" + $sourcePath = "$TestDrive/SourceDir" + $archivePath = "$TestDrive/FileAndDirTreeForExpand.zip" + $destinationPath = "$TestDrive/FileAndDirTree" $sourceList = dir $sourcePath -Name Add-CompressionAssemblies @@ -850,8 +865,8 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } It "Validate Expand-Archive cmdlet in pipleline scenario" { - $sourcePath = "$TestDrive\SamplePreCreated*.zip" - $destinationPath = "$TestDrive\PipeToExpandArchive" + $sourcePath = "$TestDrive/SamplePreCreated*.zip" + $destinationPath = "$TestDrive/PipeToExpandArchive" $content = "Some Data" $files = @("Sample-1.txt", "Sample-2.txt") @@ -867,8 +882,8 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } It "Validate that Expand-Archive generates Verbose messages" { - $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" - $destinationPath = "$TestDrive\VerboseMessagesInExpandArchive" + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $destinationPath = "$TestDrive/VerboseMessagesInExpandArchive" try { @@ -889,8 +904,8 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } It "Validate that without -Force parameter Expand-Archive generates non-terminating errors without overwriting existing files" { - $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" - $destinationPath = "$TestDrive\NoForceParameterExpandArchive" + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $destinationPath = "$TestDrive/NoForceParameterExpandArchive" try { @@ -910,10 +925,10 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } It "Validate that without DestinationPath parameter Expand-Archive cmdlet succeeds in expanding the archive" { - $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" - $archivePath = "$TestDrive\NoDestinationPathParameter.zip" - $destinationPath = "$TestDrive\NoDestinationPathParameter" - copy $sourcePath $archivePath -Force + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $archivePath = "$TestDrive/NoDestinationPathParameter.zip" + $destinationPath = "$TestDrive/NoDestinationPathParameter" + copy-item $sourcePath $archivePath -Force try { @@ -929,10 +944,10 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } It "Validate that without DestinationPath parameter Expand-Archive cmdlet succeeds in expanding the archive when destination directory exists" { - $sourcePath = "$TestDrive\SamplePreCreatedArchive.zip" - $archivePath = "$TestDrive\NoDestinationPathParameterDirExists.zip" - $destinationPath = "$TestDrive\NoDestinationPathParameterDirExists" - copy $sourcePath $archivePath -Force + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $archivePath = "$TestDrive/NoDestinationPathParameterDirExists.zip" + $destinationPath = "$TestDrive/NoDestinationPathParameterDirExists" + copy-item $sourcePath $archivePath -Force New-Item -Path $destinationPath -ItemType Directory | Out-Null try @@ -948,4 +963,4 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "BVT" { } } } -} \ No newline at end of file +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 index 088fb5cd2..4dd0e2b1b 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "History cmdlet test cases" -tags 'DRT' { +Describe "History cmdlet test cases" -Tags "CI" { It "Tests Invoke-History on a cmdlet that generates output on all streams" { $streamSpammer = ' @@ -61,4 +61,4 @@ Describe "History cmdlet test cases" -tags 'DRT' { $errorResult | Should be CommandNotFoundException } -} \ No newline at end of file +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.ps1 index b5eafffcf..5fcf4ff0f 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.ps1 @@ -2,16 +2,21 @@ ## Copyright (c) Microsoft Corporation, 2015 ## -Describe "Tests Get-Command with relative paths and wildcards" { +Describe "Tests Get-Command with relative paths and wildcards" -Tag "CI" { BeforeAll { # Create temporary EXE command files - $null = New-Item -ItemType File -Path (Join-Path $env:Temp WildCardCommandA.exe) -ErrorAction Ignore - $null = New-Item -ItemType File -Path (Join-Path $env:Temp WildCardCommand[B].exe) -ErrorAction Ignore + $file1 = Setup -f WildCardCommandA.exe -pass + $file2 = Setup -f WildCard + $null = New-Item -ItemType File -Path (Join-Path $TestDrive WildCardCommandA.exe) -ErrorAction Ignore + $null = New-Item -ItemType File -Path (Join-Path $TestDRive WildCardCommand[B].exe) -ErrorAction Ignore + if ( $IsLinux -or $IsOSX ) { + /bin/chmod +x + } } It "Test wildcard with drive relative directory path" { - $pathName = Join-Path $env:Temp "WildCardCommandA*" + $pathName = Join-Path $TestDrive "WildCardCommandA*" $pathName = $pathName.Substring(2, ($pathName.Length - 2)) $result = Get-Command -Name $pathName $result | Should Not Be $null @@ -19,15 +24,15 @@ Describe "Tests Get-Command with relative paths and wildcards" { } It "Test wildcard with relative directory path" { - pushd $env:Temp + push-location $TestDrive $result = Get-Command -Name .\WildCardCommandA* - popd + pop-location $result | Should Not Be $null $result | Should Be WildCardCommandA.exe } - It "Test with PowerShell wildcard and reative path" { - pushd $env:Temp + It "Test with PowerShell wildcard and relative path" { + push-location $TestDrive # This should use the wildcard to find WildCardCommandA.exe $result = Get-Command -Name .\WildCardCommand[A].exe @@ -39,11 +44,7 @@ Describe "Tests Get-Command with relative paths and wildcards" { $result | Should Not Be $null $result | Should Be WildCardCommand[B].exe - popd + Pop-Location } - AfterAll { - # Remove temporary files - Remove-Item -Path (Join-Path $env:Temp WildCardCommand*) -Force -ErrorAction Ignore - } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 index 60408bdb6..dd1c13a73 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 @@ -7,6 +7,7 @@ # If PS Remoting is not available, do not run the suite. function ShouldRun { + if ( $IsCore ) { return $false } $result = Invoke-Command -ComputerName . -ScriptBlock {1} -ErrorAction SilentlyContinue return ($result -eq 1) } @@ -17,7 +18,7 @@ if (-not (ShouldRun)) return } -Describe "Validate Copy-Item Remotely" -Tags "Innerloop", "DRT" { +Describe "Validate Copy-Item Remotely" -Tags "CI" { # Validate a copy item operation. # $filePath is the source file path @@ -643,7 +644,7 @@ Describe "Validate Copy-Item Remotely" -Tags "Innerloop", "DRT" { } } -Describe "Validate Copy-Item error for target sessions not in FullLanguageMode." -Tags "Innerloop", "RI", "P1" { +Describe "Validate Copy-Item error for target sessions not in FullLanguageMode." -Tags "Feature" { BeforeAll { @@ -731,7 +732,7 @@ Describe "Validate Copy-Item error for target sessions not in FullLanguageMode." } } -Describe "Copy-Item can use Recurse and Exclude together" -Tags "RI", "P1" { +Describe "Copy-Item can use Recurse and Exclude together" -Tags "Feature" { Context "Local and Remote Tests" { @@ -776,7 +777,7 @@ Describe "Copy-Item can use Recurse and Exclude together" -Tags "RI", "P1" { } } -Describe "Copy-Item remotely bug fixes" -Tags "RI", "P1" { +Describe "Copy-Item remotely bug fixes" -Tags "Feature" { BeforeAll { $s = New-PSSession -ComputerName . -ErrorAction SilentlyContinue @@ -864,4 +865,4 @@ Describe "Copy-Item remotely bug fixes" -Tags "RI", "P1" { "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" | Should Exist } } -} \ No newline at end of file +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1 index 420c2cfc2..24941dc33 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1 @@ -1,7 +1,7 @@ # Tests related to TFS item 1370133 [PSUpgrade] Need -NoNewline parameter on Out-File, Add-Content and Set-Content # Connect request https://connect.microsoft.com/PowerShell/feedback/details/524739/need-nonewline-parameter-on-out-file-add-content-and-set-content -Describe "Tests for -NoNewline parameter of Out-File, Add-Content and Set-Content" -tags 'P1', 'RI' { +Describe "Tests for -NoNewline parameter of Out-File, Add-Content and Set-Content" -tags "Feature" { It "NoNewline parameter works on Out-File" { $temp = New-TemporaryFile @@ -23,4 +23,4 @@ Describe "Tests for -NoNewline parameter of Out-File, Add-Content and Set-Conten (Get-Content $temp -Encoding Byte).Count | Should Be 9 Remove-Item $temp -ErrorAction SilentlyContinue -Force } -} \ No newline at end of file +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 index 91d05c78d..b91c7aebd 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 @@ -14,26 +14,25 @@ Hexa decimal equivalent of the input data is displayed. #> -Describe "FormatHex" -tags 'DRT' { +Describe "FormatHex" -tags "CI" { + BeforeAll { + Setup -d FormatHexDataDir + $inputText1 = 'Hello World' + $inputText2 = 'This is a bit more text' + $inputFile1 = setup -f "FormatHexDataDir/SourceFile-1.txt" -content $inputText1 -pass + $inputFile2 = setup -f "FormatHexDataDir/SourceFile-2.txt" -content $inputText2 -pass + } - New-Item TestDrive:\FormatHexDataDir -Type Directory -Force | Out-Null - $inputFile = "TestDrive:\FormatHexDataDir\SourceFile-1.txt" - $inputText = 'Hello World' - Set-Content -Value $inputText -Path $inputFile - $inputFile2 = "TestDrive:\FormatHexDataDir\SourceFile-2.txt" - $inputText2 = 'This is a bit more text' - Set-Content -Value $inputText2 -Path $inputFile2 - # This test is to validate to pipeline support in Format-Hex cmdlet. It "ValidatePipelineSupport" { # InputObject Parameter set should get invoked and # the input data should be treated as string. - $result = $inputText | Format-Hex + $result = $inputText1 | Format-Hex $result | Should Not Be $null $result.GetType().Name | Should Be 'ByteCollection' $actualResult = $result.ToString() - ($actualResult -match $inputText) | Should Be $true + ($actualResult -match $inputText1) | Should Be $true } # This test is to validate to pipeline support in Format-Hex cmdlet. @@ -41,63 +40,63 @@ Describe "FormatHex" -tags 'DRT' { # InputObject Parameter set should get invoked and # the input data should be treated as byte[]. - $inputBytes = [System.Text.Encoding]::ASCII.GetBytes($inputText) + $inputBytes = [System.Text.Encoding]::ASCII.GetBytes($inputText1) $result = Format-Hex -InputObject $inputBytes $result | Should Not Be $null $result.GetType().Name | Should Be 'ByteCollection' $actualResult = $result.ToString() - ($actualResult -match $inputText) | Should Be $true + ($actualResult -match $inputText1) | Should Be $true } # This test is to validate to input given through Path paramter set in Format-Hex cmdlet. It "ValidatePathParameterSet" { - $result = Format-Hex -Path $inputFile + $result = Format-Hex -Path $inputFile1 $result | Should Not Be $null $result.GetType().Name | Should Be 'ByteCollection' $actualResult = $result.ToString() - ($actualResult -match $inputText) | Should Be $true + ($actualResult -match $inputText1) | Should Be $true } # This test is to validate to Path paramter set is considered as default in Format-Hex cmdlet. It "ValidatePathAsDefaultParameterSet" { - $result = Format-Hex $inputFile + $result = Format-Hex $inputFile1 $result | Should Not BeNullOrEmpty $result.GetType().Name | Should Be 'ByteCollection' $actualResult = $result.ToString() - ($actualResult -match $inputText) | Should Be $true + ($actualResult -match $inputText1) | Should Be $true } # This test is to validate to input given through LiteralPath paramter set in Format-Hex cmdlet. It "ValidateLiteralPathParameterSet" { - $result = Format-Hex -LiteralPath $inputFile + $result = Format-Hex -LiteralPath $inputFile1 $result | Should Not BeNullOrEmpty $result.GetType().Name | Should Be 'ByteCollection' $actualResult = $result.ToString() - ($actualResult -match $inputText) | Should Be $true + ($actualResult -match $inputText1) | Should Be $true } # This test is to validate to input given through pipeline. The input being piped from results of Get-hildItem It "ValidateFileInfoPipelineInput" { - $result = Get-ChildItem $inputFile | Format-Hex + $result = Get-ChildItem $inputFile1 | Format-Hex $result | Should Not BeNullOrEmpty $result.GetType().Name | Should Be 'ByteCollection' $actualResult = $result.ToString() - ($actualResult -match $inputText) | Should Be $true + ($actualResult -match $inputText1) | Should Be $true } # This test is to validate Encoding formats functionality of Format-Hex cmdlet. It "ValidateEncodingFormats" { - $result = Format-Hex -InputObject $inputText -Encoding ASCII + $result = Format-Hex -InputObject $inputText1 -Encoding ASCII $result | Should Not BeNullOrEmpty $result.GetType().Name | Should Be 'ByteCollection' $actualResult = $result.ToString() - ($actualResult -match $inputText) | Should Be $true + ($actualResult -match $inputText1) | Should Be $true } # This test is to validate that integers can be piped to the format-hex @@ -190,15 +189,19 @@ Describe "FormatHex" -tags 'DRT' { $result | Should Not BeNullOrEmpty $result.Count | should be 2 $result[0].ToString() | Should be "00000000 54 68 69 73 20 69 73 20 61 20 62 69 74 20 6D 6F This is a bit mo" - $result[1].ToString() | Should be "00000010 72 65 20 74 65 78 74 0D 0A re text.. " + if ( $IsCore ) { + $result[1].ToString() | Should be "00000010 72 65 20 74 65 78 74 re text " + } } # This test ensures that if we stream bytes from a file, the output is correct It "ValidateStreamOfBytesFromFileHasProperOutput" { - $result = Get-Content $InputFile -Encoding Byte | Format-Hex + $result = Get-Content $InputFile1 -Encoding Byte | Format-Hex $result | Should Not BeNullOrEmpty $result.GetType().Name | Should Be "ByteCollection" - $result.ToString() | Should be "00000000 48 65 6C 6C 6F 20 57 6F 72 6C 64 0D 0A Hello World.. " + if ( $IsCore ) { + $result.ToString() | Should be "00000000 48 65 6C 6C 6F 20 57 6F 72 6C 64 Hello World " + } } # This test is to validate the alias for Format-Hex cmdlet. diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 index 7c1a2f974..73aa5a9b8 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "Using delimiters with Export-CSV and Import-CSV behave correctly" -tags P1 { +Describe "Using delimiters with Export-CSV and Import-CSV behave correctly" -tags "Feature" { BeforeAll { # note, we will not use "," as that's the default for CSV $delimiters = "/", " ", "@", "#", "$", "\", "&", "(", ")", @@ -6,6 +6,9 @@ Describe "Using delimiters with Export-CSV and Import-CSV behave correctly" -tag '"', "~", "!", "%", "^", "*", "_", "+", ":", "?", "-", "=", "[", "]", "." $defaultDelimiter = [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator + # With CORECLR the CurrentCulture.TextInfo.ListSeparator is not writable, so + # we need to use an entirely new CultureInfo which we can modify + $enCulture = [System.Globalization.CultureInfo]::new("en-us") $d = get-date $testCases = @( foreach($del in $delimiters) @@ -13,9 +16,25 @@ Describe "Using delimiters with Export-CSV and Import-CSV behave correctly" -tag @{ Delimiter = $del; Data = $d; ExpectedResult = $d.Ticks } } ) + function Set-delimiter { + param ( $delimiter ) + if ( $IsCore ) { + $enCulture.TextInfo.ListSeparator = $delimiter + [System.Globalization.CultureInfo]::CurrentCulture = $enCulture + } + else { + [System.Globalization.cultureInfo]::CurrentCulture.TextInfo.ListSeparator = $delimiter + } + } } AfterEach { - [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator = $defaultDelimiter + if ( $IsCore ) { + $enCulture.TextInfo.ListSeparator = $defaultDelimiter + [System.Globalization.CultureInfo]::CurrentCulture = $enCulture + } + else { + [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator = $defaultDelimiter + } remove-item -force -ea silentlycontinue TESTDRIVE:/file.csv } @@ -42,7 +61,7 @@ Describe "Using delimiters with Export-CSV and Import-CSV behave correctly" -tag # parameter generated tests It 'Delimiter with CSV import will fail correctly when culture does not match' -testCases $testCases { param ($delimiter, $Data, $ExpectedResult) - [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator = $delimiter + set-Delimiter $delimiter $Data | export-CSV TESTDRIVE:\File.csv -useCulture $i = Import-CSV TESTDRIVE:\File.csv $i.Ticks | Should Not Be $ExpectedResult @@ -50,7 +69,7 @@ Describe "Using delimiters with Export-CSV and Import-CSV behave correctly" -tag It 'Delimiter with CSV import will succeed when culture matches export' -testCases $testCases { param ($delimiter, $Data, $ExpectedResult) - [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator = $delimiter + set-Delimiter $delimiter $Data | export-CSV TESTDRIVE:\File.csv -useCulture $i = Import-CSV TESTDRIVE:\File.csv -useCulture $i.Ticks | Should Be $ExpectedResult diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1 index 9e6138387..831a1292a 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "GetDateFormatUpdates" -tags 'P1', 'RI' { +Describe "GetDateFormatUpdates" -Tags "Feature" { It "Verifies that FileDate format works" { $date = Get-Date @@ -34,7 +34,7 @@ Describe "GetDateFormatUpdates" -tags 'P1', 'RI' { } -Describe "GetRandomMiscTests" -tags 'P1', 'RI' { +Describe "GetRandomMiscTests" -Tags "Feature" { It "Shouldn't overflow when using max range" { $hadError = $false @@ -51,4 +51,4 @@ Describe "GetRandomMiscTests" -tags 'P1', 'RI' { $hadError | Should be $false } -} \ No newline at end of file +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1 index 1a912a27b..39757d61d 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1 @@ -1,4 +1,4 @@ -Describe -Tags "Unit","DRT" "New-Guid" { +Describe "New-Guid" -Tags "CI" { It "returns a new guid" { $guid = New-Guid diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1 index e705cb4a2..0c496b4a5 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1 @@ -14,7 +14,7 @@ A FileInfo object for the temporary file is returned. #> -Describe "NewTemporaryFile" -tags 'DRT' { +Describe "NewTemporaryFile" -Tags "CI" { It "creates a new temporary file" { $tempFile = New-TemporaryFile diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.JsonTests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.JsonTests.ps1 index 913ee65e3..da48d6dd7 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.JsonTests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.JsonTests.ps1 @@ -8,7 +8,7 @@ # This 'Describe' is for tests that were converted from utscripts (SDXROOT/admin/monad/tests/monad/DRT/utscripts) # and C# tests (SDXROOT/admin/monad/tests/monad/DRT/commands/utility/UnitTests) to Pester. # -Describe "Json Tests" -Tags "RI", "P1" { +Describe "Json Tests" -Tags "Feature" { BeforeAll { @@ -144,7 +144,7 @@ namespace Bug378368 $response.d.Name.First | Should Match "Joel" } - It "Convert to Json using PSOjbect" { + It "Convert to Json using PSObject" -pending:($IsCore) { $response = ConvertFrom-Json '{"d":{"__type":"SimpleJsonObject","Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' @@ -204,7 +204,7 @@ namespace Bug378368 $response2 | Should Be $result3 } - It "Convert to Json using hashtable" { + It "Convert to Json using hashtable" -pending:($IsCore) { $nameHash = @{First="Joe1";Last="Wood"} $dHash = @{Name=$nameHash; Greeting="Hello"} @@ -393,14 +393,14 @@ namespace Bug378368 # This Describe is for new Json tests # -Describe "Validate Json serialization" -Tags "BVT" { +Describe "Validate Json serialization" -Tags "CI" { Context "Validate Json serialization ascii values" { $testCases = @( @{ TestInput = 0 - ToJson = 'null' + ToJson = if ( $IsCore ) { '"\u0000"' } else { 'null' } FromJson = '' } @{ @@ -590,12 +590,12 @@ Describe "Validate Json serialization" -Tags "BVT" { } @{ TestInput = 38 - ToJson = '"\u0026"' + ToJson = if ( $IsCore ) { '"&"' } else { '"\u0026"' } FromJson = '&' } @{ TestInput = 39 - ToJson = '"\u0027"' + ToJson = if ( $IsCore ) { '"''"' } else { '"\u0027"' } FromJson = "'" } @{ @@ -700,7 +700,7 @@ Describe "Validate Json serialization" -Tags "BVT" { } @{ TestInput = 60 - ToJson = '"\u003c"' + ToJson = if ( $IsCore ) { '"<"' } else { '"\u003c"' } FromJson = '<' } @{ @@ -710,7 +710,7 @@ Describe "Validate Json serialization" -Tags "BVT" { } @{ TestInput = 62 - ToJson = '"\u003e"' + ToJson = if ( $IsCore ) { '">"' } else { '"\u003e"' } FromJson = '>' } @{ @@ -1265,7 +1265,8 @@ Describe "Validate Json serialization" -Tags "BVT" { { param ($testCase) - It "Validate '$($testCase.TestInput) | ConvertTo-Json' and '$($testCase.TestInput) | ConvertTo-Json | ConvertFrom-Json'" { + if ( $TestCase.TestInput -eq "[char]::MinValue" ) { $pending = $true } else { $pending = $false } + It "Validate '$($testCase.TestInput) | ConvertTo-Json' and '$($testCase.TestInput) | ConvertTo-Json | ConvertFrom-Json'" -pending:$pending { # The test case input is executed via invoke-expression. Then, we use this value as an input to ConvertTo-Json, # and the result is saved into in the $result.ToJson variable. Lastly, this value is deserialized back using @@ -1321,7 +1322,7 @@ Describe "Validate Json serialization" -Tags "BVT" { } } - It "Validate that CimClass Properties for win32_bios can be serialized using ConvertTo-Json and ConvertFrom-Json" { + It "Validate that CimClass Properties for win32_bios can be serialized using ConvertTo-Json and ConvertFrom-Json" -skip { $class = Get-CimClass win32_bios @@ -1361,7 +1362,7 @@ Describe "Validate Json serialization" -Tags "BVT" { $a = 1..5 $b = 6..10 - $actual = @{'a'=$a;'b'=$b} | ConvertTo-Json + $actual = [ordered]@{'a'=$a;'b'=$b} | ConvertTo-Json $expected = @' { "a": [ @@ -1385,7 +1386,7 @@ Describe "Validate Json serialization" -Tags "BVT" { } } -Describe "Json Bug fixes" -Tags "RI", "P1" { +Describe "Json Bug fixes" -Tags "Feature" { function RunJsonTest { @@ -1462,4 +1463,4 @@ Describe "Json Bug fixes" -Tags "RI", "P1" { { RunJsonTest $testCase } -} \ No newline at end of file +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 index 0d0deff9a..f26a7e4c8 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 @@ -1,11 +1,11 @@ -Describe "Tests for the Import-PowerShellDataFile cmdlet" -Tags 'P1', 'RI' { +Describe "Tests for the Import-PowerShellDataFile cmdlet" -Tags "Feature" { It "Validates error on a missing path" { $foundError = "" try { - Import-PowerShellDataFile -Path c:\SomeMissingDirectory -ErrorAction Stop + Import-PowerShellDataFile -Path /SomeMissingDirectory -ErrorAction Stop } catch { @@ -20,7 +20,7 @@ Describe "Tests for the Import-PowerShellDataFile cmdlet" -Tags 'P1', 'RI' { $foundError = "" try { - Import-PowerShellDataFile ($env:SYSTEMDRIVE + '\') -ErrorAction Stop + Import-PowerShellDataFile ${TESTDRIVE} -ErrorAction Stop } catch { @@ -83,4 +83,4 @@ Describe "Tests for the Import-PowerShellDataFile cmdlet" -Tags 'P1', 'RI' { $result.Hello | Should be "World" } -} \ No newline at end of file +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/alias.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/alias.tests.ps1 index 8e1e94011..2ed3956d6 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/alias.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/alias.tests.ps1 @@ -1,4 +1,4 @@ -Describe "Alias tests" -Tags "innerloop", "P1", "RI" { +Describe "Alias tests" -Tags "CI" { BeforeAll { $testPath = Join-Path testdrive:\ ("testAlias\[.test") @@ -157,4 +157,4 @@ Describe "Alias tests" -Tags "innerloop", "P1", "RI" { $definedAlias.Definition | Should Be "update-help" } } -} \ No newline at end of file +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 index 957df5117..4ae526145 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 @@ -1,4 +1,4 @@ -Describe "CliXml test" -Tags "innerloop", "P1", "RI" { +Describe "CliXml test" -Tags "CI" { BeforeAll { $testFilePath = Join-Path "testdrive:\" "testCliXml" @@ -184,4 +184,4 @@ Describe "CliXml test" -Tags "innerloop", "P1", "RI" { $testPath | Should Not Exist } } -} \ No newline at end of file +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 index 5480603b5..94d554989 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 @@ -1,29 +1,29 @@ -Describe "Trace-Command" -tags "P1", "RI" { +Describe "Trace-Command" -tags "Feature" { Context "Listner options" { BeforeAll { - $logFile = New-Item "TestDrive:\traceCommandLog.txt" -Force - $actualLogFile = New-Item "TestDrive:\actualTraceCommandLog.txt" -Force + $logFile = setup -f traceCommandLog.txt -pass + $actualLogFile = setup -f actualTraceCommandLog.txt -pass } AfterEach { - Remove-Item "TestDrive:\traceCommandLog.txt" -Force -ErrorAction SilentlyContinue - Remove-Item "TestDrive:\actualTraceCommandLog.txt" -Force -ErrorAction SilentlyContinue + if ( test-path $logfile ) { Remove-Item $logFile } + if ( test-path $actualLogFile ) { Remove-Item $actualLogFile } } - It "LogicalOperationStack works" { + It "LogicalOperationStack works" -pending:($IsCore) { $keyword = "Trace_Command_ListenerOption_LogicalOperationStack_Foo" $stack = [System.Diagnostics.Trace]::CorrelationManager.LogicalOperationStack $stack.Push($keyword) - Trace-Command -Name * -Expression {echo Foo} -ListenerOption LogicalOperationStack -FilePath $logfile + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption LogicalOperationStack -FilePath $logfile $log = Get-Content $logfile | Where-Object {$_ -like "*LogicalOperationStack=$keyword*"} $log.Count | Should BeGreaterThan 0 } - It "Callstack works" { - Trace-Command -Name * -Expression {echo Foo} -ListenerOption Callstack -FilePath $logfile + It "Callstack works" -pending:($IsCore) { + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption Callstack -FilePath $logfile $log = Get-Content $logfile | Where-Object {$_ -like "*Callstack= * System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)*"} $log.Count | Should BeGreaterThan 0 } @@ -47,14 +47,14 @@ Describe "Trace-Command" -tags "P1", "RI" { } It "None options has no effect" { - Trace-Command -Name * -Expression {echo Foo} -ListenerOption None -FilePath $actualLogfile - Trace-Command -name * -Expression {echo Foo} -FilePath $logfile + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption None -FilePath $actualLogfile + Trace-Command -name * -Expression {write-output Foo} -FilePath $logfile Compare-Object (Get-Content $actualLogfile) (Get-Content $logfile) | Should BeNullOrEmpty } It "ThreadID works" { - Trace-Command -Name * -Expression {echo Foo} -ListenerOption ThreadId -FilePath $logfile + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption ThreadId -FilePath $logfile $log = Get-Content $logfile | Where-Object {$_ -like "*ThreadID=*"} $results = $log | ForEach-Object {$_.Split("=")[1]} @@ -62,7 +62,7 @@ Describe "Trace-Command" -tags "P1", "RI" { } It "Timestamp creates logs in ascending order" { - Trace-Command -Name * -Expression {echo Foo} -ListenerOption Timestamp -FilePath $logfile + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption Timestamp -FilePath $logfile $log = Get-Content $logfile | Where-Object {$_ -like "*Timestamp=*"} $results = $log | ForEach-Object {$_.Split("=")[1]} $sortedResults = $results | Sort-Object @@ -70,11 +70,11 @@ Describe "Trace-Command" -tags "P1", "RI" { } It "ProcessId logs current process Id" { - Trace-Command -Name * -Expression {echo Foo} -ListenerOption ProcessId -FilePath $logfile + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption ProcessId -FilePath $logfile $log = Get-Content $logfile | Where-Object {$_ -like "*ProcessID=*"} $results = $log | ForEach-Object {$_.Split("=")[1]} $results | ForEach-Object { $_ | Should Be $pid } } } -} \ No newline at end of file +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1 index 02d54a42f..d1f08eeef 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1 @@ -1,11 +1,11 @@ -Describe "FormatData" -tags "P1", "RI" { +Describe "FormatData" -tags "Feature" { Context "Export" { It "can export all types" { try { $expectAllFormat = Get-FormatData -typename * - $expectAllFormat | Export-FormatData -path $env:temp\allformat.ps1xml -IncludeScriptBlock + $expectAllFormat | Export-FormatData -path $TESTDRIVE\allformat.ps1xml -IncludeScriptBlock $sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() $sessionState.Formats.Clear() @@ -14,7 +14,7 @@ Describe "FormatData" -tags "P1", "RI" { $runspace = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace($sessionState) $runspace.Open() - $runspace.CreatePipeline("Update-FormatData -AppendPath $env:temp\allformat.ps1xml").Invoke() + $runspace.CreatePipeline("Update-FormatData -AppendPath $TESTDRIVE\allformat.ps1xml").Invoke() $actualAllFormat = $runspace.CreatePipeline("Get-FormatData -TypeName *").Invoke() $expectAllFormat.Count | Should Be $actualAllFormat.Count @@ -23,7 +23,7 @@ Describe "FormatData" -tags "P1", "RI" { } finally { - Remove-Item -Path $env:temp\allformat.ps1xml -Force -ErrorAction SilentlyContinue + Remove-Item -Path $TESTDRIVE\allformat.ps1xml -Force -ErrorAction SilentlyContinue } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/object.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/object.tests.ps1 index 496917101..41d4bf2ea 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/object.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/object.tests.ps1 @@ -1,4 +1,4 @@ -Describe "Object cmdlets" -Tags 'innerloop', 'P1', 'RI' { +Describe "Object cmdlets" -Tags "CI" { Context "Group-Object" { It "AsHashtable returns a hashtable" { $result = Get-Process | Group-Object -Property ProcessName -AsHashTable @@ -21,7 +21,7 @@ Describe "Object cmdlets" -Tags 'innerloop', 'P1', 'RI' { } } -Describe "Object cmdlets" -Tags 'DRT' { +Describe "Object cmdlets" -Tags "CI" { Context "Measure-Object" { BeforeAll { ## Powershell language prefers , as an array seperator without "". @@ -97,4 +97,4 @@ Describe "Object cmdlets" -Tags 'DRT' { $gmi.Count | Should Be 2 } } -} \ No newline at end of file +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 index 0282df288..bdcfa965d 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 @@ -1,6 +1,7 @@ -Describe "String cmdlets" -Tags 'innerloop', 'P1', 'RI' { +Describe "String cmdlets" -Tags "CI" { Context "Select-String" { BeforeAll { + $sep = [io.path]::DirectorySeparatorChar $fileName = New-Item 'TestDrive:\selectStr[ingLi]teralPath.txt' "abc" | Out-File -LiteralPath $fileName.fullname "bcd" | Out-File -LiteralPath $fileName.fullname -Append @@ -35,12 +36,13 @@ Describe "String cmdlets" -Tags 'innerloop', 'P1', 'RI' { (select-string -LiteralPath $fileNameWithDots "b").count | Should Be 2 } - It "Network path" { + It "Network path" -skip:($IsCore) { (select-string -LiteralPath $fileNameAsNetworkPath "b").count | Should Be 2 } It "throws error for non filesystem providers" { - select-string -literalPath cert:\currentuser\my "a" -ErrorAction SilentlyContinue -ErrorVariable selectStringError + $aaa = "aaaaaaaaaa" + select-string -literalPath variable:\aaa "a" -ErrorAction SilentlyContinue -ErrorVariable selectStringError $selectStringError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectStringCommand' } @@ -49,7 +51,7 @@ Describe "String cmdlets" -Tags 'innerloop', 'P1', 'RI' { } It "match object supports RelativePath method" { - $file = "Modules\Microsoft.PowerShell.Utility\Microsoft.PowerShell.Utility.psd1" + $file = "Modules${sep}Microsoft.PowerShell.Utility${sep}Microsoft.PowerShell.Utility.psd1" $match = Select-String CmdletsToExport $pshome/$file diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/typedata.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/typedata.tests.ps1 index 6e3288fc54aadf0c86a80cb1402bfe53c9b94207..5f88d447af4675db30638b6ea701ecea02873503 100644 GIT binary patch delta 98 zcmX>X{2*w88>kgG|C3TOROnmogMEC@|tC`hMh_T*NOV zuM3n*WGG?C0ICZC>MaJcU4SNJGL!*%R+D=rG$$AEvv7t1Rpl_0GNf*9BpWq^K0Kk1K6aWAK diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 index f2985945d..119d30a01 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 @@ -1,4 +1,4 @@ -Describe "XML cmdlets" -Tags 'P1', 'RI' { +Describe "XML cmdlets" -Tags "Feature" { Context "Select-XML" { BeforeAll { $fileName = New-Item -Path 'TestDrive:\testSelectXml.xml' @@ -28,11 +28,15 @@ Describe "XML cmdlets" -Tags 'P1', 'RI' { $testcases += [TestData]::new('literalpath with relative paths', @{LiteralPath = $fileName.Name; XPath = 'Root'}) $testcases += [TestData]::new('literalpath with absolute paths', @{LiteralPath = $fileName.FullName; XPath = 'Root'}) $testcases += [TestData]::new('literalpath with path with dots', @{LiteralPath = $fileNameWithDots; XPath = 'Root'}) - $testcases += [TestData]::new('literalpath with network path', @{LiteralPath = $fileNameAsNetworkPath; XPath = 'Root'}) + if ( ! $IsCore ) { + $testcases += [TestData]::new('literalpath with network path', @{LiteralPath = $fileNameAsNetworkPath; XPath = 'Root'}) + } $testcases += [TestData]::new('path with relative paths', @{Path = $fileName.Name; XPath = 'Root'}) $testcases += [TestData]::new('path with absolute paths', @{Path = $fileName.FullName; XPath = 'Root'}) $testcases += [TestData]::new('path with path with dots', @{Path = $fileNameWithDots; XPath = 'Root'}) - $testcases += [TestData]::new('path with network path', @{Path = $fileNameAsNetworkPath; XPath = 'Root'}) + if ( ! $IsCore ) { + $testcases += [TestData]::new('path with network path', @{Path = $fileNameAsNetworkPath; XPath = 'Root'}) + } } AfterAll { @@ -50,13 +54,15 @@ Describe "XML cmdlets" -Tags 'P1', 'RI' { } It "literalpath with non filesystem path" { - Select-XML -literalPath cert:\currentuser\my "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue + $__data = "abcdefg" + Select-XML -literalPath variable:__data "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue $selectXmlError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand' } It "path with non filesystem path" { - Select-XML -Path cert:\currentuser\my "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue + $__data = "abcdefg" + Select-XML -Path variable:\__data "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue $selectXmlError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand' } } -} \ No newline at end of file +} From 3575eac7b345d6c394acaf1db9db68a48a31b966 Mon Sep 17 00:00:00 2001 From: PowerShell Team Date: Thu, 21 Jul 2016 11:10:36 -0700 Subject: [PATCH 12/25] fix typo in archive test name it needs to have the correct name in order to be executed by invoke-pester --- test/powershell/Modules/map.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/powershell/Modules/map.json b/test/powershell/Modules/map.json index 29f7a8dd9..6d474cc95 100644 --- a/test/powershell/Modules/map.json +++ b/test/powershell/Modules/map.json @@ -4,7 +4,7 @@ "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/MiscCmdletUpdates.Tests.ps1": "Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1", "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/NewGuid.Tests.ps1": "Microsoft.PowerShell.Utility/NewGuid.Tests.ps1", "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/NewTemporaryFile.Tests.ps1": "Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.ArchiveTests.ps1": "Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.ArchiveTests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.ArchiveTests.ps1": "Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1", "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/SamplePreCreatedArchive.archive": "Microsoft.PowerShell.Archive/SamplePreCreatedArchive.archive", "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.GetCommand.ps1": "Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.ps1", "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.JsonTests.ps1": "Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.JsonTests.ps1", From 176f9fb6bd1c349dcae750e61f9d9285c2834095 Mon Sep 17 00:00:00 2001 From: James Truher Date: Thu, 21 Jul 2016 11:13:19 -0700 Subject: [PATCH 13/25] rename archive test file so it may be found by invoke-pester --- ...ArchiveTests.ps1 => Pester.Commands.Cmdlets.Archive.Tests.ps1} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/powershell/Modules/Microsoft.PowerShell.Archive/{Pester.Commands.Cmdlets.ArchiveTests.ps1 => Pester.Commands.Cmdlets.Archive.Tests.ps1} (100%) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.ArchiveTests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 similarity index 100% rename from test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.ArchiveTests.ps1 rename to test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 From d23a5fddc70641621cfbaae72d7c15cb09caef8a Mon Sep 17 00:00:00 2001 From: James Truher Date: Thu, 21 Jul 2016 11:13:47 -0700 Subject: [PATCH 14/25] fix Archive module to work correctly when the DirectorySeparatorChar is "/" rather than use either "/" or "\", just use [io.path]::DirectorySeparatorChar --- .../Microsoft.PowerShell.Archive.psm1 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Modules/Shared/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psm1 b/src/Modules/Shared/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psm1 index e179118c2..56daf78d8 100644 --- a/src/Modules/Shared/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psm1 +++ b/src/Modules/Shared/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psm1 @@ -662,13 +662,13 @@ function CompressSingleDirHelper } else { - $modifiedSourceDirFullName = $sourceDirFullName + "\" + $modifiedSourceDirFullName = $sourceDirFullName + ([io.path]::DirectorySeparatorChar) } } else { $sourceDirFullName = $sourceDirPath - $modifiedSourceDirFullName = $sourceDirFullName + "\" + $modifiedSourceDirFullName = $sourceDirFullName + ([io.path]::DirectorySeparatorChar) } $dirContents = Get-ChildItem -LiteralPath $sourceDirPath -Recurse @@ -688,7 +688,7 @@ function CompressSingleDirHelper $files = $currentContent.GetFiles() if($files.Count -eq 0) { - $subDirFiles.Add($currentContent.FullName + "\") + $subDirFiles.Add($currentContent.FullName + ([io.path]::DirectorySeparatorChar)) } } } @@ -780,7 +780,7 @@ function ZipArchiveHelper # If a directory needs to be added to an archive file, # by convention the .Net API's expect the path of the diretcory # to end with '\' to detect the path as an directory. - if(!$relativeFilePath.EndsWith("\", [StringComparison]::OrdinalIgnoreCase)) + if(!$relativeFilePath.EndsWith(([io.path]::DirectorySeparatorChar), [StringComparison]::OrdinalIgnoreCase)) { try { @@ -951,7 +951,7 @@ function ExpandArchiveHelper # The current archive entry is an empty directory # The FullName of the Archive Entry representing a directory would end with a trailing '\'. if($extension -eq [string]::Empty -and - $currentArchiveEntryPath.EndsWith("\", [StringComparison]::OrdinalIgnoreCase)) + $currentArchiveEntryPath.EndsWith(([io.path]::DirectorySeparatorChar), [StringComparison]::OrdinalIgnoreCase)) { $pathExists = Test-Path -LiteralPath $currentArchiveEntryPath From 1d11f67376f4d04eb8763192e8e131ff46873441 Mon Sep 17 00:00:00 2001 From: PowerShell Team Date: Thu, 21 Jul 2016 11:34:49 -0700 Subject: [PATCH 15/25] fix two more file copy targets they weren't being recognized as pester tests because they didn't have the right name --- test/powershell/Modules/map.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/powershell/Modules/map.json b/test/powershell/Modules/map.json index 6d474cc95..9f91f5633 100644 --- a/test/powershell/Modules/map.json +++ b/test/powershell/Modules/map.json @@ -6,8 +6,8 @@ "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/NewTemporaryFile.Tests.ps1": "Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1", "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.ArchiveTests.ps1": "Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1", "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/SamplePreCreatedArchive.archive": "Microsoft.PowerShell.Archive/SamplePreCreatedArchive.archive", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.GetCommand.ps1": "Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.ps1", - "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.JsonTests.ps1": "Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.JsonTests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.GetCommand.ps1": "Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1", + "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.JsonTests.ps1": "Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1", "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1": "Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1", "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.History.Tests.ps1": "Microsoft.PowerShell.Core/History.Tests.ps1", "monad/tests/ci/PowerShell/tests/Commands/Cmdlets/Pester.Management.Copy.Item.Tests.ps1": "Microsoft.PowerShell.Management/Copy.Item.Tests.ps1", From 96a81c626c8ad57f30e75ba35e45d06c48a44d70 Mon Sep 17 00:00:00 2001 From: James Truher Date: Thu, 21 Jul 2016 11:39:32 -0700 Subject: [PATCH 16/25] rename test files so they match map.json and can be found by invoke-pester --- ...etCommand.ps1 => Pester.Commands.Cmdlets.GetCommand.Tests.ps1} | 0 ...dlets.JsonTests.ps1 => Pester.Commands.Cmdlets.Json.Tests.ps1} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test/powershell/Modules/Microsoft.PowerShell.Core/{Pester.Commands.Cmdlets.GetCommand.ps1 => Pester.Commands.Cmdlets.GetCommand.Tests.ps1} (100%) rename test/powershell/Modules/Microsoft.PowerShell.Utility/{Pester.Commands.Cmdlets.JsonTests.ps1 => Pester.Commands.Cmdlets.Json.Tests.ps1} (100%) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 similarity index 100% rename from test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.ps1 rename to test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.JsonTests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 similarity index 100% rename from test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.JsonTests.ps1 rename to test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 From 0f60b69af4d31262110f0d96acd2d5c6efa14e3e Mon Sep 17 00:00:00 2001 From: James Truher Date: Thu, 21 Jul 2016 11:44:12 -0700 Subject: [PATCH 17/25] Fix Get-Command tests to better handle non-Windows platforms. set executable bit on Linux/MacOS as that's what determines whether something is executable. Also simplify partial path creation, only remove up to the first colon, so those filesystems which have a single root are treated properly --- .../Pester.Commands.Cmdlets.GetCommand.Tests.ps1 | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 index 5fcf4ff0f..0c99c4270 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 @@ -7,17 +7,19 @@ Describe "Tests Get-Command with relative paths and wildcards" -Tag "CI" { BeforeAll { # Create temporary EXE command files $file1 = Setup -f WildCardCommandA.exe -pass - $file2 = Setup -f WildCard - $null = New-Item -ItemType File -Path (Join-Path $TestDrive WildCardCommandA.exe) -ErrorAction Ignore - $null = New-Item -ItemType File -Path (Join-Path $TestDRive WildCardCommand[B].exe) -ErrorAction Ignore + $file2 = Setup -f WildCardCommand[B].exe -pass + #$null = New-Item -ItemType File -Path (Join-Path $TestDrive WildCardCommandA.exe) -ErrorAction Ignore + #$null = New-Item -ItemType File -Path (Join-Path $TestDRive WildCardCommand[B].exe) -ErrorAction Ignore if ( $IsLinux -or $IsOSX ) { - /bin/chmod +x + /bin/chmod 777 "$file1" + /bin/chmod 777 "$file2" } } It "Test wildcard with drive relative directory path" { $pathName = Join-Path $TestDrive "WildCardCommandA*" - $pathName = $pathName.Substring(2, ($pathName.Length - 2)) + $driveOffset = $pathName.IndexOf(":") + $pathName = $pathName.Substring($driveOffset + 1) $result = Get-Command -Name $pathName $result | Should Not Be $null $result.Name | Should Be WildCardCommandA.exe From 7b836f99f5a26d5481ff6a58c157add51447594e Mon Sep 17 00:00:00 2001 From: James Truher Date: Thu, 21 Jul 2016 14:51:08 -0700 Subject: [PATCH 18/25] create work-around for MacOS in handling wildcards --- .../Pester.Commands.Cmdlets.Archive.Tests.ps1 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 index f4a5db6ff..3c1d055f2 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 @@ -386,7 +386,8 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { } finally { - Remove-Item -LiteralPath $sourcePath -Force + get-item -literalPath $sourcePath | remove-Item -force + # Remove-Item -LiteralPath $sourcePath -Force } } It "Validate that Compress-Archive cmdlet errors out when DestinationPath resolves to multiple locations" { @@ -441,7 +442,8 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { } finally { - Remove-Item -LiteralPath $sourcePath -Force -Recurse + get-item -LiteralPath $sourcePath | Remove-Item -Force -Recurse + # Remove-Item -LiteralPath $sourcePath -Force -Recurse } } It "Validate that Compress-Archive cmdlet can accept DestinationPath parameter with Special Characters" { @@ -454,7 +456,8 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { } finally { - Remove-Item -LiteralPath $destinationPath -Force + Get-Item -LiteralPath $destinationPath | Remove-Item -Force + # Remove-Item -LiteralPath $destinationPath -Force } } It "Validate that Source Path can be at SystemDrive location" -skip:($IsCore) { From dd0291be09c91083ef04f9443b7319bf345f16d3 Mon Sep 17 00:00:00 2001 From: James Truher Date: Mon, 25 Jul 2016 11:06:55 -0700 Subject: [PATCH 19/25] update encoding on the test files - these are ascii --- .../Pester.Commands.Cmdlets.Archive.Tests.ps1 | 1938 +++++------ .../History.Tests.ps1 | 128 +- ...ster.Commands.Cmdlets.GetCommand.Tests.ps1 | 104 +- .../Copy.Item.Tests.ps1 | 1736 +++++----- ...mands.Cmdlets.NoNewlineParameter.Tests.ps1 | 52 +- .../FormatHex.Tests.ps1 | 442 +-- .../ImportExportCSV.Delimiter.Tests.ps1 | 168 +- .../MiscCmdletUpdates.Tests.ps1 | 108 +- .../NewGuid.Tests.ps1 | 38 +- .../NewTemporaryFile.Tests.ps1 | 76 +- .../Pester.Commands.Cmdlets.Json.Tests.ps1 | 2891 ++++++++--------- .../PowerShellData.tests.ps1 | 172 +- .../alias.tests.ps1 | 320 +- .../clixml.tests.ps1 | 374 +-- .../command.tests.ps1 | 160 +- .../formatdata.tests.ps1 | 128 +- .../object.tests.ps1 | 200 +- .../string.tests.ps1 | 126 +- .../typedata.tests.ps1 | Bin 10592 -> 5169 bytes .../xml.tests.ps1 | 136 +- 20 files changed, 4628 insertions(+), 4669 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 index 3c1d055f2..f8ac581f8 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 @@ -1,969 +1,969 @@ -<############################################################################################ - # File: Pester.Commands.Cmdlets.ArchiveTests.ps1 - # Commands.Cmdlets.ArchiveTests suite contains Tests that are - # used for validating Microsoft.PowerShell.Archive module. - ############################################################################################> -$script:TestSourceRoot = $PSScriptRoot -Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { - - AfterAll { - $global:ProgressPreference = $_progressPreference - } - BeforeAll { - # Write-Progress not supported yet on Core - $_progressPreference = $ProgressPreference - if ( $IsCore ) { $global:ProgressPreference = "SilentlyContinue" } - - Setup -d SourceDir - Setup -d SourceDir/ChildDir-1 - Setup -d SourceDir/ChildDir-2 - Setup -d SourceDir/ChildEmptyDir - - $content = "Some Data" - $Files = ( [io.path]::Combine("SourceDir","Sample-1.txt")), ([io.path]::Combine("SourceDir","Sample-2.txt")), - ([io.path]::Combine("SourceDir","ChildDir-1","Sample-3.txt")), ([io.path]::Combine("SourceDir","ChildDir-1","Sample-4.txt")), - ([io.path]::Combine("SourceDir","ChildDir-2","Sample-5.txt")), ([io.path]::Combine("SourceDir","ChildDir-2","Sample-6.txt")) - - foreach($file in $files ) { - Setup -f $file -content $content - } - - Setup -f Sample.unzip -content "Some Text" - Setup -f Sample.cab -content "Some Text" - - $preCreatedArchivePath = Join-Path $script:TestSourceRoot "SamplePreCreatedArchive.archive" - Copy-Item $preCreatedArchivePath $TestDrive/SamplePreCreatedArchive.zip -Force - } - - function Add-CompressionAssemblies { - Add-Type -AssemblyName System.IO.Compression - if (($psedition -eq "Core") -or $IsCore ) - { - Add-Type -AssemblyName System.IO.Compression.ZipFile - } - else - { - Add-Type -AssemblyName System.IO.Compression.FileSystem - } - } - - function CompressArchivePathParameterSetValidator { - param - ( - [string[]] $path, - [string] $destinationPath, - [string] $compressionLevel = "Optimal" - ) - - try - { - Compress-Archive -Path $path -DestinationPath $destinationPath -CompressionLevel $compressionLevel - trow "ValidateNotNullOrEmpty attribute is missing on one of parameters belonging to Path parameterset." - } - catch - { - $_.FullyQualifiedErrorId | Should Be "ParameterArgumentValidationError,Compress-Archive" - } - } - - function CompressArchiveLiteralPathParameterSetValidator { - param - ( - [string[]] $literalPath, - [string] $destinationPath, - [string] $compressionLevel = "Optimal" - ) - - try - { - Compress-Archive -LiteralPath $literalPath -DestinationPath $destinationPath -CompressionLevel $compressionLevel - throw "ValidateNotNullOrEmpty attribute is missing on one of parameters belonging to LiteralPath parameterset." - } - catch - { - $_.FullyQualifiedErrorId | Should Be "ParameterArgumentValidationError,Compress-Archive" - } - } - - - function CompressArchiveInValidPathValidator { - param - ( - [string[]] $path, - [string] $destinationPath, - [string] $invalidPath, - [string] $expectedFullyQualifiedErrorId - ) - - try - { - Compress-Archive -Path $path -DestinationPath $destinationPath - throw "Failed to validate that an invalid Path $invalidPath was supplied as input to Compress-Archive cmdlet." - } - catch - { - $_.FullyQualifiedErrorId | Should Be $expectedFullyQualifiedErrorId - } - } - - function CompressArchiveInValidArchiveFileExtensionValidator { - param - ( - [string[]] $path, - [string] $destinationPath, - [string] $invalidArchiveFileExtension - ) - - try - { - Compress-Archive -Path $path -DestinationPath $destinationPath - throw "Failed to validate that an invalid archive file format $invalidArchiveFileExtension was supplied as input to Compress-Archive cmdlet." - } - catch - { - $_.FullyQualifiedErrorId | Should Be "NotSupportedArchiveFileExtension,Compress-Archive" - } - } - - function Validate-ArchiveEntryCount { - param - ( - [string] $path, - [int] $expectedEntryCount - ) - - Add-CompressionAssemblies - try - { - $archiveFileStreamArgs = @($path, [System.IO.FileMode]::Open) - $archiveFileStream = New-Object -TypeName System.IO.FileStream -ArgumentList $archiveFileStreamArgs - - $zipArchiveArgs = @($archiveFileStream, [System.IO.Compression.ZipArchiveMode]::Read, $false) - $zipArchive = New-Object -TypeName System.IO.Compression.ZipArchive -ArgumentList $zipArchiveArgs - - $actualEntryCount = $zipArchive.Entries.Count - $actualEntryCount | Should Be $expectedEntryCount - } - finally - { - if ($null -ne $zipArchive) { $zipArchive.Dispose()} - if ($null -ne $archiveFileStream) { $archiveFileStream.Dispose() } - } - } - - function ArchiveFileEntryContentValidator { - param - ( - [string] $path, - [string] $entryFileName, - [string] $expectedEntryFileContent - ) - - Add-CompressionAssemblies - try - { - $destFile = "$TestDrive/ExpandedFile"+([System.Guid]::NewGuid().ToString())+".txt" - - $archiveFileStreamArgs = @($path, [System.IO.FileMode]::Open) - $archiveFileStream = New-Object -TypeName System.IO.FileStream -ArgumentList $archiveFileStreamArgs - - $zipArchiveArgs = @($archiveFileStream, [System.IO.Compression.ZipArchiveMode]::Read, $false) - $zipArchive = New-Object -TypeName System.IO.Compression.ZipArchive -ArgumentList $zipArchiveArgs - - $entryToBeUpdated = $zipArchive.Entries | ? {$_.FullName -eq $entryFileName} - - if($entryToBeUpdated -ne $null) - { - $srcStream = $entryToBeUpdated.Open() - $destStream = New-Object "System.IO.FileStream" -ArgumentList( $destFile, [System.IO.FileMode]::Create ) - $srcStream.CopyTo( $destStream ) - $destStream.Dispose() - $srcStream.Dispose() - Get-Content $destFile | Should Be $expectedEntryFileContent - } - else - { - throw "Failed to find the file $entryFileName in the archive file $path" - } - } - finally - { - if ($zipArchive) - { - $zipArchive.Dispose() - } - if ($archiveFileStream) - { - $archiveFileStream.Dispose() - } - } - } - - function ExpandArchiveInvalidParameterValidator { - param - ( - [boolean] $isLiteralPathParameterSet, - [string[]] $path, - [string] $destinationPath, - [string] $expectedFullyQualifiedErrorId - ) - - try - { - if($isLiteralPathParameterSet) - { - Expand-Archive -LiteralPath $literalPath -DestinationPath $destinationPath - } - else - { - Expand-Archive -Path $path -DestinationPath $destinationPath - } - - throw "Expand-Archive did NOT throw expected error" - } - catch - { - $_.FullyQualifiedErrorId | Should Be $expectedFullyQualifiedErrorId - } - } - - Context "Compress-Archive - Parameter validation test cases" { - - It "Validate errors from Compress-Archive with NULL & EMPTY values for Path, LiteralPath, DestinationPath, CompressionLevel parameters" { - $sourcePath = "$TestDrive/SourceDir" - $destinationPath = "$TestDrive/SampleSingleFile.zip" - - CompressArchivePathParameterSetValidator $null $destinationPath - CompressArchivePathParameterSetValidator $sourcePath $null - CompressArchivePathParameterSetValidator $null $null - - CompressArchivePathParameterSetValidator "" $destinationPath - CompressArchivePathParameterSetValidator $sourcePath "" - CompressArchivePathParameterSetValidator "" "" - - CompressArchivePathParameterSetValidator $null $null "NoCompression" - - CompressArchiveLiteralPathParameterSetValidator $null $destinationPath - CompressArchiveLiteralPathParameterSetValidator $sourcePath $null - CompressArchiveLiteralPathParameterSetValidator $null $null - - CompressArchiveLiteralPathParameterSetValidator "" $destinationPath - CompressArchiveLiteralPathParameterSetValidator $sourcePath "" - CompressArchiveLiteralPathParameterSetValidator "" "" - - CompressArchiveLiteralPathParameterSetValidator $null $null "NoCompression" - - CompressArchiveLiteralPathParameterSetValidator $sourcePath $destinationPath $null - CompressArchiveLiteralPathParameterSetValidator $sourcePath $destinationPath "" - } - - It "Validate errors from Compress-Archive when invalid path (non-existing path / non-filesystem path) is supplied for Path or LiteralPath parameters" { - CompressArchiveInValidPathValidator "$TestDrive/InvalidPath" $TestDrive "$TestDrive/InvalidPath" "ArchiveCmdletPathNotFound,Compress-Archive" - if ( ! $IsCore ) { - CompressArchiveInValidPathValidator "HKLM:/SOFTWARE" $TestDrive "HKLM:/SOFTWARE" "PathNotFound,Compress-Archive" - } - CompressArchiveInValidPathValidator "$TestDrive" "$TestDrive/NonExistingDirectory/sample.zip" "$TestDrive/NonExistingDirectory/sample.zip" "ArchiveCmdletPathNotFound,Compress-Archive" - - $path = @("$TestDrive", "$TestDrive/InvalidPath") - CompressArchiveInValidPathValidator $path $TestDrive "$TestDrive/InvalidPath" "ArchiveCmdletPathNotFound,Compress-Archive" - - if ( ! $IsCore ) { - $path = @("$TestDrive", "HKLM:/SOFTWARE") - CompressArchiveInValidPathValidator $path $TestDrive "HKLM:/SOFTWARE" "PathNotFound,Compress-Archive" - } - - $invalidUnZipFileFormat = "$TestDrive/Sample.unzip" - CompressArchiveInValidArchiveFileExtensionValidator $TestDrive "$invalidUnZipFileFormat" ".unzip" - - $invalidcabZipFileFormat = "$TestDrive/Sample.cab" - CompressArchiveInValidArchiveFileExtensionValidator $TestDrive "$invalidcabZipFileFormat" ".cab" - } - - It "Validate error from Compress-Archive when archive file already exists and -Update parameter is not specified" { - $sourcePath = "$TestDrive/SourceDir" - $destinationPath = "$TestDrive/ValidateErrorWhenUpdateNotSpecified.zip" - - try - { - "Some Data" > $destinationPath - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - throw "Failed to validate that an archive file format $destinationPath already exists and -Update switch parameter is not specified while running Compress-Archive command." - } - catch - { - $_.FullyQualifiedErrorId | Should Be "ArchiveFileExists,Compress-Archive" - } - } - - It "Validate error from Compress-Archive when duplicate paths are supplied as input to Path parameter" { - $sourcePath = @( - "$TestDrive/SourceDir/Sample-1.txt", - "$TestDrive/SourceDir/Sample-1.txt") - $destinationPath = "$TestDrive/DuplicatePaths.zip" - - try - { - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - throw "Failed to detect that duplicate Path $sourcePath is supplied as input to Path parameter." - } - catch - { - $_.FullyQualifiedErrorId | Should Be "DuplicatePathFound,Compress-Archive" - } - } - - It "Validate error from Compress-Archive when duplicate paths are supplied as input to LiteralPath parameter" { - $sourcePath = @( - "$TestDrive/SourceDir/Sample-1.txt", - "$TestDrive/SourceDir/Sample-1.txt") - $destinationPath = "$TestDrive/DuplicatePaths.zip" - - try - { - Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath - throw "Failed to detect that duplicate Path $sourcePath is supplied as input to LiteralPath parameter." - } - catch - { - $_.FullyQualifiedErrorId | Should Be "DuplicatePathFound,Compress-Archive" - } - } - - It "Validate that relative path can be specified as Path parameter of Compress-Archive cmdlet" { - $sourcePath = "./SourceDir" - $destinationPath = "RelativePathForPathParameter.zip" - try { - push-location $TESTDRIVE - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - finally { - Pop-Location - } - } - It "Validate that relative path can be specified as LiteralPath parameter of Compress-Archive cmdlet" { - $sourcePath = "./SourceDir" - $destinationPath = "RelativePathForLiteralPathParameter.zip" - try { - push-location $TESTDRIVE - Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - finally { - Pop-Location - } - } - It "Validate that relative path can be specified as DestinationPath parameter of Compress-Archive cmdlet" { - $sourcePath = "$TestDrive/SourceDir" - $destinationPath = "./RelativePathForDestinationPathParameter.zip" - try { - push-location $TESTDRIVE - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - finally { - Pop-Location - } - } - } - - Context "Compress-Archive - functional test cases" { - It "Validate that a single file can be compressed using Compress-Archive cmdlet" { - $sourcePath = [io.path]::Combine("$TestDrive","SourceDir","ChildDir-1","Sample-3.txt") - $destinationPath = [io.path]::Combine("$TestDrive","SampleSingleFile.zip") - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - $destinationPath | Should Exist - } - # This test requires a fix in PS5 to support reading paths with square bracket - It "Validate that Compress-Archive cmdlet can accept LiteralPath parameter with Special Characters" -skip:($PSVersionTable.psversion -lt "5.0") { - $sourcePath = "$TestDrive/SourceDir/ChildDir-1/Sample[]File.txt" - "Some Random Content" | Out-File -LiteralPath $sourcePath - $destinationPath = "$TestDrive/SampleSingleFileWithSpecialCharacters.zip" - try - { - Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath - $destinationPath | Should Exist - } - finally - { - get-item -literalPath $sourcePath | remove-Item -force - # Remove-Item -LiteralPath $sourcePath -Force - } - } - It "Validate that Compress-Archive cmdlet errors out when DestinationPath resolves to multiple locations" { - - New-Item $TestDrive/SampleDir/Child-1 -Type Directory -Force | Out-Null - New-Item $TestDrive/SampleDir/Child-2 -Type Directory -Force | Out-Null - New-Item $TestDrive/SampleDir/Test.txt -Type File -Force | Out-Null - - $destinationPath = "$TestDrive/SampleDir/Child-*/SampleChidArchive.zip" - $sourcePath = "$TestDrive/SampleDir/Test.txt" - try - { - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - throw "Failed to detect that destination $destinationPath can resolve to multiple paths" - } - catch - { - $_.FullyQualifiedErrorId | Should Be "InvalidArchiveFilePath,Compress-Archive" - } - finally - { - Remove-Item -LiteralPath $TestDrive/SampleDir -Force -Recurse - } - } - It "Validate that Compress-Archive cmdlet works when DestinationPath has wild card pattern and resolves to a single valid path" { - - New-Item $TestDrive/SampleDir/Child-1 -Type Directory -Force | Out-Null - New-Item $TestDrive/SampleDir/Test.txt -Type File -Force | Out-Null - - $destinationPath = "$TestDrive/SampleDir/Child-*/SampleChidArchive.zip" - $sourcePath = "$TestDrive/SampleDir/Test.txt" - try - { - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - $destinationPath | Should Exist - } - finally - { - Remove-Item -LiteralPath $TestDrive/SampleDir -Force -Recurse - } - } - # This test requires a fix in PS5 to support reading paths with square bracket - It "Validate that Compress-Archive cmdlet can accept LiteralPath parameter for a directory with Special Characters in the directory name" -skip:($PSVersionTable.psversion -lt "5.0") { - $sourcePath = "$TestDrive/Source[]Dir/ChildDir[]-1" - New-Item $sourcePath -Type Directory | Out-Null - "Some Random Content" | Out-File -LiteralPath "$sourcePath/Sample[]File.txt" - $destinationPath = "$TestDrive/SampleDirWithSpecialCharacters.zip" - try - { - Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath - $destinationPath | Should Exist - } - finally - { - get-item -LiteralPath $sourcePath | Remove-Item -Force -Recurse - # Remove-Item -LiteralPath $sourcePath -Force -Recurse - } - } - It "Validate that Compress-Archive cmdlet can accept DestinationPath parameter with Special Characters" { - $sourcePath = "$TestDrive/SourceDir/ChildDir-1/Sample-3.txt" - $destinationPath = "$TestDrive/Sample[]SingleFile.zip" - try - { - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path -LiteralPath $destinationPath | Should Be $true - } - finally - { - Get-Item -LiteralPath $destinationPath | Remove-Item -Force - # Remove-Item -LiteralPath $destinationPath -Force - } - } - It "Validate that Source Path can be at SystemDrive location" -skip:($IsCore) { - $sourcePath = "$env:SystemDrive/SourceDir" - $destinationPath = "$TestDrive/SampleFromSystemDrive.zip" - New-Item $sourcePath -Type Directory | Out-Null - "Some Data" | Out-File -FilePath $sourcePath/SampleSourceFileForArchive.txt - try - { - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - finally - { - remove-item "$sourcePath" -Force -Recurse -ErrorAction SilentlyContinue - } - } - It "Validate that multiple files can be compressed using Compress-Archive cmdlet" { - $sourcePath = @( - "$TestDrive/SourceDir/ChildDir-1/Sample-3.txt", - "$TestDrive/SourceDir/ChildDir-1/Sample-4.txt", - "$TestDrive/SourceDir/ChildDir-2/Sample-5.txt", - "$TestDrive/SourceDir/ChildDir-2/Sample-6.txt") - $destinationPath = "$TestDrive/SampleMultipleFiles.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - It "Validate that multiple files and directories can be compressed using Compress-Archive cmdlet" { - $sourcePath = @( - "$TestDrive/SourceDir/Sample-1.txt", - "$TestDrive/SourceDir/Sample-2.txt", - "$TestDrive/SourceDir/ChildDir-1", - "$TestDrive/SourceDir/ChildDir-2") - $destinationPath = "$TestDrive/SampleMultipleFilesAndDirs.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - It "Validate that a single directory can be compressed using Compress-Archive cmdlet" { - $sourcePath = @("$TestDrive/SourceDir/ChildDir-1") - $destinationPath = "$TestDrive/SampleSingleDir.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - It "Validate that a single directory with multiple files and subdirectories can be compressed using Compress-Archive cmdlet" { - $sourcePath = @("$TestDrive/SourceDir") - $destinationPath = "$TestDrive/SampleSubTree.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - It "Validate that a single directory & multiple files can be compressed using Compress-Archive cmdlet" { - $sourcePath = @( - "$TestDrive/SourceDir/ChildDir-1", - "$TestDrive/SourceDir/Sample-1.txt", - "$TestDrive/SourceDir/Sample-2.txt") - $destinationPath = "$TestDrive/SampleMultipleFilesAndSingleDir.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - - It "Validate that if .zip extension is not supplied as input to DestinationPath parameter, then .zip extension is appended" { - $sourcePath = @("$TestDrive/SourceDir") - $destinationPath = "$TestDrive/SampleNoExtension.zip" - $destinationWithoutExtensionPath = "$TestDrive/SampleNoExtension" - Compress-Archive -Path $sourcePath -DestinationPath $destinationWithoutExtensionPath - Test-Path $destinationPath | Should Be $true - } - - It "Validate that -Update parameter makes Compress-Archive to not throw an error if archive file already exists" { - $sourcePath = @("$TestDrive/SourceDir") - $destinationPath = "$TestDrive/SampleUpdateTest.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update - Test-Path $destinationPath | Should Be $true - } - It "Validate -Update parameter by adding a new file to an existing archive file" { - $sourcePath = @("$TestDrive/SourceDir/ChildDir-1") - $destinationPath = "$TestDrive/SampleUpdateAdd1File.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - New-Item $TestDrive/SourceDir/ChildDir-1/Sample-AddedNewFile.txt -Type File | Out-Null - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update - Test-Path $destinationPath | Should Be $true - Validate-ArchiveEntryCount -path $destinationPath -expectedEntryCount 3 - } - - It "Validate that all CompressionLevel values can be used with Compress-Archive cmdlet" { - $sourcePath = "$TestDrive/SourceDir/Sample-1.txt" - - $destinationPath = "$TestDrive/FastestCompressionLevel.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel Fastest - Test-Path $destinationPath | Should Be $true - - $destinationPath = "$TestDrive/OptimalCompressionLevel.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel Optimal - Test-Path $destinationPath | Should Be $true - - $destinationPath = "$TestDrive/NoCompressionCompressionLevel.zip" - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel NoCompression - Test-Path $destinationPath | Should Be $true - } - - It "Validate that -Update parameter is modifying a file that already exists in the archive file" { - $filePath = "$TestDrive/SourceDir/ChildDir-1/Sample-3.txt" - - $initialContent = "Initial Content" - $modifiedContent = "Modified Content" - - $initialContent | Set-Content $filePath - - $sourcePath = "$TestDrive/SourceDir" - $destinationPath = "$TestDrive/UpdatingModifiedFile.zip" - - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $True - - $modifiedContent | Set-Content $filePath - - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update - Test-Path $destinationPath | Should Be $True - - ArchiveFileEntryContentValidator "$destinationPath" ([io.path]::Combine("SourceDir","ChildDir-1","Sample-3.txt")) $modifiedContent - } - - It "Validate Compress-Archive cmdlet in pipleline scenario" { - $destinationPath = "$TestDrive/CompressArchiveFromPipeline.zip" - - # Piping a single file path to Compress-Archive - dir -Path $TestDrive/SourceDir/Sample-1.txt | Compress-Archive -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $True - - # Piping a string directory path to Compress-Archive - "$TestDrive/SourceDir/ChildDir-2" | Compress-Archive -DestinationPath $destinationPath -Update - Test-Path $destinationPath | Should Be $True - - # Piping the output of Get-ChildItem to Compress-Archive - dir "$TestDrive/SourceDir" -Recurse | Compress-Archive -DestinationPath $destinationPath -Update - Test-Path $destinationPath | Should Be $True - } - - It "Validate that Compress-Archive works on ReadOnly files" { - $sourcePath = "$TestDrive/ReadOnlyFile.txt" - $destinationPath = "$TestDrive/TestForReadOnlyFile.zip" - - "Some Content" | Out-File -FilePath $sourcePath - $createdItem = Get-Item $sourcePath - $createdItem.Attributes = 'ReadOnly' - - Compress-Archive -Path $sourcePath -DestinationPath $destinationPath - Test-Path $destinationPath | Should Be $true - } - - It "Validate that Compress-Archive generates Verbose messages" { - $sourcePath = "$TestDrive/SourceDir" - $destinationPath = "$TestDrive/Compress-Archive generates VerboseMessages.zip" - - try - { - $ps=[PowerShell]::Create() - $ps.Streams.Error.Clear() - $ps.Streams.Verbose.Clear() - $script = "Import-Module Microsoft.PowerShell.Archive; Compress-Archive -Path $sourcePath -DestinationPath `"$destinationPath`" -CompressionLevel Fastest -Verbose" - $ps.AddScript($script) - $ps.Invoke() - - $ps.Streams.Verbose.Count -gt 0 | Should Be $True - $ps.Streams.Error.Count | Should Be 0 - } - finally - { - $ps.Dispose() - } - } - } - - Context "Expand-Archive - Parameter validation test cases" { - It "Validate non existing archive -Path trows expected error message" { - $sourcePath = "$TestDrive/SourceDir" - $destinationPath = "$TestDrive/ExpandedArchive" - try - { - Expand-Archive -Path $sourcePath -DestinationPath $destinationPath - throw "Expand-Archive succeeded for non existing archive path" - } - catch - { - $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" - } - } - - It "Validate errors from Expand-Archive with NULL & EMPTY values for Path, LiteralPath, DestinationPath parameters" { - ExpandArchiveInvalidParameterValidator $false $null "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $false $null $null "ParameterArgumentValidationError,Expand-Archive" - - ExpandArchiveInvalidParameterValidator $false "$TestDrive/SourceDir" $null "ParameterArgumentTransformationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $false "" "$TestDrive/SourceDir" "ParameterArgumentTransformationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $false "$TestDrive/SourceDir" "" "ParameterArgumentTransformationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $false "" "" "ParameterArgumentTransformationError,Expand-Archive" - - ExpandArchiveInvalidParameterValidator $true $null "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true $null $null "ParameterArgumentValidationError,Expand-Archive" - - ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" $null "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "" "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" "" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "" "" "ParameterArgumentValidationError,Expand-Archive" - - ExpandArchiveInvalidParameterValidator $true $null "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true $null $null "ParameterArgumentValidationError,Expand-Archive" - - ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" $null "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "" "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" "" "ParameterArgumentValidationError,Expand-Archive" - ExpandArchiveInvalidParameterValidator $true "" "" "ParameterArgumentValidationError,Expand-Archive" - } - - It "Validate errors from Expand-Archive when invalid path (non-existing path / non-filesystem path) is supplied for Path or LiteralPath parameters" { - try { Expand-Archive -Path "$TestDrive/NonExistingArchive" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } - catch { $_.FullyQualifiedErrorId | Should Be "ArchiveCmdletPathNotFound,Expand-Archive" } - - if ( ! $IsCore ) { - try { Expand-Archive -Path "HKLM:/SOFTWARE" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } - catch { $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" } - } - - try { Expand-Archive -LiteralPath "$TestDrive/NonExistingArchive" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } - catch { $_.FullyQualifiedErrorId | Should Be "ArchiveCmdletPathNotFound,Expand-Archive" } - - if ( ! $IsCore ) { - try { Expand-Archive -LiteralPath "HKLM:/SOFTWARE" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } - catch { $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" } - } - } - - It "Validate error from Expand-Archive when invalid path (non-existing path / non-filesystem path) is supplied for DestinationPath parameter" { - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - # $destinationPath = "HKLM:/SOFTWARE" - $destinationPath = "Variable:/" - - try { Expand-Archive -Path $sourcePath -DestinationPath $destinationPath; throw "Expand-Archive did NOT throw expected error" } - catch { $_.FullyQualifiedErrorId | Should Be "InvalidDirectoryPath,Expand-Archive" } - } - } - - Context "Expand-Archive - functional test cases" { - It "Validate basic Expand-Archive scenario" { - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - $content = "Some Data" - $destinationPath = "$TestDrive/DestDirForBasicExpand" - $files = @("Sample-1.txt", "Sample-2.txt") - - # The files in "$TestDrive/SamplePreCreatedArchive.zip" are precreated. - $fileCreationTimeStamp = Get-Date -Year 2014 -Month 6 -Day 13 -Hour 15 -Minute 50 -Second 20 -Millisecond 0 - - Expand-Archive -Path $sourcePath -DestinationPath $destinationPath - foreach($currentFile in $files) - { - $expandedFile = Join-Path $destinationPath -ChildPath $currentFile - Test-Path $expandedFile | Should Be $True - - # We are validating to make sure that time stamps are preserved in the - # compressed archive are reflected back when the file is expanded. - (dir $expandedFile).LastWriteTime.CompareTo($fileCreationTimeStamp) | Should Be 0 - - Get-Content $expandedFile | Should Be $content - } - } - It "Validate that Expand-Archive cmdlet errors out when DestinationPath resolves to multiple locations" { - $testbasename = "TargetDir" - setup -d "$testbasename" - setup -d "$testbasename/Child-1" - setup -d "$testbasename/Child-2" - - $destinationPath = [io.path]::Combine("$TestDrive","$testbasename","Child-*") - $sourcePath = join-path "$TestDrive" "SamplePreCreatedArchive.zip" - try - { - Expand-Archive -Path $sourcePath -DestinationPath $destinationPath - throw "Failed to detect that destination $destinationPath can resolve to multiple paths" - } - catch - { - $_.FullyQualifiedErrorId | Should Be "InvalidDestinationPath,Expand-Archive" - } - finally - { - Remove-Item -LiteralPath "$TestDrive/$testbasename" -Force -Recurse - } - } - It "Validate that Expand-Archive cmdlet works when DestinationPath resolves has wild card pattern and resolves to a single valid path" { - $testbasename = "TargetDir" - setup -d "$testbasename" - setup -d "$testbasename/Child-1" - - $destinationPath = [io.path]::Combine("$TestDrive","$testbasename","Child-*") - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - try - { - Expand-Archive -Path $sourcePath -DestinationPath $destinationPath - $expandedFiles = Get-ChildItem $destinationPath -Recurse - $expandedFiles.Length | Should BeGreaterThan 1 - } - finally - { - Remove-Item -LiteralPath "$TestDrive/$testbasename" -Force -Recurse - } - } - It "Validate Expand-Archive scenario where DestinationPath has Special Characters" { - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - $content = "Some Data" - $destinationPath = "$TestDrive/DestDir[]Expand" - $files = @("Sample-1.txt", "Sample-2.txt") - - # The files in "$TestDrive/SamplePreCreatedArchive.zip" are precreated. - $fileCreationTimeStamp = Get-Date -Year 2014 -Month 6 -Day 13 -Hour 15 -Minute 50 -Second 20 -Millisecond 0 - - Expand-Archive -Path $sourcePath -DestinationPath $destinationPath - foreach($currentFile in $files) - { - $expandedFile = Join-Path $destinationPath -ChildPath $currentFile - Test-Path -LiteralPath $expandedFile | Should Be $True - - # We are validating to make sure that time stamps are preserved in the - # compressed archive are reflected back when the file is expanded. - (dir -LiteralPath $expandedFile).LastWriteTime.CompareTo($fileCreationTimeStamp) | Should Be 0 - - Get-Content -LiteralPath $expandedFile | Should Be $content - } - } - It "Invoke Expand-Archive with relative path in Path parameter and -Force parameter" { - $sourcePath = "./SamplePreCreatedArchive.zip" - $destinationPath = "$TestDrive/SomeOtherNonExistingDir/Path" - try - { - Push-Location $TestDrive - - Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Force - $expandedFiles = Get-ChildItem $destinationPath -Recurse - $expandedFiles.Length | Should Be 2 - } - finally - { - Pop-Location - } - } - - It "Invoke Expand-Archive with relative path in LiteralPath parameter and -Force parameter" { - $sourcePath = "./SamplePreCreatedArchive.zip" - $destinationPath = "$TestDrive/SomeOtherNonExistingDir/LiteralPath" - try - { - Push-Location $TestDrive - - Expand-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath -Force - $expandedFiles = Get-ChildItem $destinationPath -Recurse - $expandedFiles.Length | Should Be 2 - } - finally - { - Pop-Location - } - } - - It "Invoke Expand-Archive with non-existing relative directory in DestinationPath parameter and -Force parameter" { - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - $destinationPath = "./SomeOtherNonExistingDir/DestinationPath" - try - { - Push-Location $TestDrive - - Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Force - $expandedFiles = Get-ChildItem $destinationPath -Recurse - $expandedFiles.Length | Should Be 2 - } - finally - { - Pop-Location - } - } - - It "Invoke Expand-Archive with unsupported archive format" { - $sourcePath = "$TestDrive/Sample.cab" - $destinationPath = "$TestDrive/UnsupportedArchiveFormatDir" - try - { - Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Force - throw "Failed to detect unsupported archive format at $sourcePath" - } - catch - { - $_.FullyQualifiedErrorId | Should Be "NotSupportedArchiveFileExtension,Expand-Archive" - } - } - - It "Invoke Expand-Archive with archive file containing multiple files, directories with subdirectories and empty directories" { - $sourcePath = "$TestDrive/SourceDir" - $archivePath = "$TestDrive/FileAndDirTreeForExpand.zip" - $destinationPath = "$TestDrive/FileAndDirTree" - $sourceList = dir $sourcePath -Name - - Add-CompressionAssemblies - [System.IO.Compression.ZipFile]::CreateFromDirectory($sourcePath, $archivePath) - - Expand-Archive -Path $archivePath -DestinationPath $destinationPath - $extractedList = dir $destinationPath -Name - - Compare-Object -ReferenceObject $extractedList -DifferenceObject $sourceList -PassThru | Should Be $null - } - - It "Validate Expand-Archive cmdlet in pipleline scenario" { - $sourcePath = "$TestDrive/SamplePreCreated*.zip" - $destinationPath = "$TestDrive/PipeToExpandArchive" - - $content = "Some Data" - $files = @("Sample-1.txt", "Sample-2.txt") - - dir $sourcePath | Expand-Archive -DestinationPath $destinationPath - - foreach($currentFile in $files) - { - $expandedFile = Join-Path $destinationPath -ChildPath $currentFile - Test-Path $expandedFile | Should Be $True - Get-Content $expandedFile | Should Be $content - } - } - - It "Validate that Expand-Archive generates Verbose messages" { - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - $destinationPath = "$TestDrive/VerboseMessagesInExpandArchive" - - try - { - $ps=[PowerShell]::Create() - $ps.Streams.Error.Clear() - $ps.Streams.Verbose.Clear() - $script = "Import-Module Microsoft.PowerShell.Archive; Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Verbose" - $ps.AddScript($script) - $ps.Invoke() - - $ps.Streams.Verbose.Count -gt 0 | Should Be $True - $ps.Streams.Error.Count | Should Be 0 - } - finally - { - $ps.Dispose() - } - } - - It "Validate that without -Force parameter Expand-Archive generates non-terminating errors without overwriting existing files" { - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - $destinationPath = "$TestDrive/NoForceParameterExpandArchive" - - try - { - $ps=[PowerShell]::Create() - $ps.Streams.Error.Clear() - $ps.Streams.Verbose.Clear() - $script = "Import-Module Microsoft.PowerShell.Archive; Expand-Archive -Path $sourcePath -DestinationPath $destinationPath; Expand-Archive -Path $sourcePath -DestinationPath $destinationPath" - $ps.AddScript($script) - $ps.Invoke() - - $ps.Streams.Error.Count -gt 0 | Should Be $True - } - finally - { - $ps.Dispose() - } - } - - It "Validate that without DestinationPath parameter Expand-Archive cmdlet succeeds in expanding the archive" { - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - $archivePath = "$TestDrive/NoDestinationPathParameter.zip" - $destinationPath = "$TestDrive/NoDestinationPathParameter" - copy-item $sourcePath $archivePath -Force - - try - { - Push-Location $TestDrive - - Expand-Archive -Path $archivePath - (dir $destinationPath).Count | Should Be 2 - } - finally - { - Pop-Location - } - } - - It "Validate that without DestinationPath parameter Expand-Archive cmdlet succeeds in expanding the archive when destination directory exists" { - $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" - $archivePath = "$TestDrive/NoDestinationPathParameterDirExists.zip" - $destinationPath = "$TestDrive/NoDestinationPathParameterDirExists" - copy-item $sourcePath $archivePath -Force - New-Item -Path $destinationPath -ItemType Directory | Out-Null - - try - { - Push-Location $TestDrive - - Expand-Archive -Path $archivePath - (dir $destinationPath).Count | Should Be 2 - } - finally - { - Pop-Location - } - } - } -} +<############################################################################################ + # File: Pester.Commands.Cmdlets.ArchiveTests.ps1 + # Commands.Cmdlets.ArchiveTests suite contains Tests that are + # used for validating Microsoft.PowerShell.Archive module. + ############################################################################################> +$script:TestSourceRoot = $PSScriptRoot +Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { + + AfterAll { + $global:ProgressPreference = $_progressPreference + } + BeforeAll { + # Write-Progress not supported yet on Core + $_progressPreference = $ProgressPreference + if ( $IsCore ) { $global:ProgressPreference = "SilentlyContinue" } + + Setup -d SourceDir + Setup -d SourceDir/ChildDir-1 + Setup -d SourceDir/ChildDir-2 + Setup -d SourceDir/ChildEmptyDir + + $content = "Some Data" + $Files = ( [io.path]::Combine("SourceDir","Sample-1.txt")), ([io.path]::Combine("SourceDir","Sample-2.txt")), + ([io.path]::Combine("SourceDir","ChildDir-1","Sample-3.txt")), ([io.path]::Combine("SourceDir","ChildDir-1","Sample-4.txt")), + ([io.path]::Combine("SourceDir","ChildDir-2","Sample-5.txt")), ([io.path]::Combine("SourceDir","ChildDir-2","Sample-6.txt")) + + foreach($file in $files ) { + Setup -f $file -content $content + } + + Setup -f Sample.unzip -content "Some Text" + Setup -f Sample.cab -content "Some Text" + + $preCreatedArchivePath = Join-Path $script:TestSourceRoot "SamplePreCreatedArchive.archive" + Copy-Item $preCreatedArchivePath $TestDrive/SamplePreCreatedArchive.zip -Force + } + + function Add-CompressionAssemblies { + Add-Type -AssemblyName System.IO.Compression + if (($psedition -eq "Core") -or $IsCore ) + { + Add-Type -AssemblyName System.IO.Compression.ZipFile + } + else + { + Add-Type -AssemblyName System.IO.Compression.FileSystem + } + } + + function CompressArchivePathParameterSetValidator { + param + ( + [string[]] $path, + [string] $destinationPath, + [string] $compressionLevel = "Optimal" + ) + + try + { + Compress-Archive -Path $path -DestinationPath $destinationPath -CompressionLevel $compressionLevel + trow "ValidateNotNullOrEmpty attribute is missing on one of parameters belonging to Path parameterset." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "ParameterArgumentValidationError,Compress-Archive" + } + } + + function CompressArchiveLiteralPathParameterSetValidator { + param + ( + [string[]] $literalPath, + [string] $destinationPath, + [string] $compressionLevel = "Optimal" + ) + + try + { + Compress-Archive -LiteralPath $literalPath -DestinationPath $destinationPath -CompressionLevel $compressionLevel + throw "ValidateNotNullOrEmpty attribute is missing on one of parameters belonging to LiteralPath parameterset." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "ParameterArgumentValidationError,Compress-Archive" + } + } + + + function CompressArchiveInValidPathValidator { + param + ( + [string[]] $path, + [string] $destinationPath, + [string] $invalidPath, + [string] $expectedFullyQualifiedErrorId + ) + + try + { + Compress-Archive -Path $path -DestinationPath $destinationPath + throw "Failed to validate that an invalid Path $invalidPath was supplied as input to Compress-Archive cmdlet." + } + catch + { + $_.FullyQualifiedErrorId | Should Be $expectedFullyQualifiedErrorId + } + } + + function CompressArchiveInValidArchiveFileExtensionValidator { + param + ( + [string[]] $path, + [string] $destinationPath, + [string] $invalidArchiveFileExtension + ) + + try + { + Compress-Archive -Path $path -DestinationPath $destinationPath + throw "Failed to validate that an invalid archive file format $invalidArchiveFileExtension was supplied as input to Compress-Archive cmdlet." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "NotSupportedArchiveFileExtension,Compress-Archive" + } + } + + function Validate-ArchiveEntryCount { + param + ( + [string] $path, + [int] $expectedEntryCount + ) + + Add-CompressionAssemblies + try + { + $archiveFileStreamArgs = @($path, [System.IO.FileMode]::Open) + $archiveFileStream = New-Object -TypeName System.IO.FileStream -ArgumentList $archiveFileStreamArgs + + $zipArchiveArgs = @($archiveFileStream, [System.IO.Compression.ZipArchiveMode]::Read, $false) + $zipArchive = New-Object -TypeName System.IO.Compression.ZipArchive -ArgumentList $zipArchiveArgs + + $actualEntryCount = $zipArchive.Entries.Count + $actualEntryCount | Should Be $expectedEntryCount + } + finally + { + if ($null -ne $zipArchive) { $zipArchive.Dispose()} + if ($null -ne $archiveFileStream) { $archiveFileStream.Dispose() } + } + } + + function ArchiveFileEntryContentValidator { + param + ( + [string] $path, + [string] $entryFileName, + [string] $expectedEntryFileContent + ) + + Add-CompressionAssemblies + try + { + $destFile = "$TestDrive/ExpandedFile"+([System.Guid]::NewGuid().ToString())+".txt" + + $archiveFileStreamArgs = @($path, [System.IO.FileMode]::Open) + $archiveFileStream = New-Object -TypeName System.IO.FileStream -ArgumentList $archiveFileStreamArgs + + $zipArchiveArgs = @($archiveFileStream, [System.IO.Compression.ZipArchiveMode]::Read, $false) + $zipArchive = New-Object -TypeName System.IO.Compression.ZipArchive -ArgumentList $zipArchiveArgs + + $entryToBeUpdated = $zipArchive.Entries | ? {$_.FullName -eq $entryFileName} + + if($entryToBeUpdated -ne $null) + { + $srcStream = $entryToBeUpdated.Open() + $destStream = New-Object "System.IO.FileStream" -ArgumentList( $destFile, [System.IO.FileMode]::Create ) + $srcStream.CopyTo( $destStream ) + $destStream.Dispose() + $srcStream.Dispose() + Get-Content $destFile | Should Be $expectedEntryFileContent + } + else + { + throw "Failed to find the file $entryFileName in the archive file $path" + } + } + finally + { + if ($zipArchive) + { + $zipArchive.Dispose() + } + if ($archiveFileStream) + { + $archiveFileStream.Dispose() + } + } + } + + function ExpandArchiveInvalidParameterValidator { + param + ( + [boolean] $isLiteralPathParameterSet, + [string[]] $path, + [string] $destinationPath, + [string] $expectedFullyQualifiedErrorId + ) + + try + { + if($isLiteralPathParameterSet) + { + Expand-Archive -LiteralPath $literalPath -DestinationPath $destinationPath + } + else + { + Expand-Archive -Path $path -DestinationPath $destinationPath + } + + throw "Expand-Archive did NOT throw expected error" + } + catch + { + $_.FullyQualifiedErrorId | Should Be $expectedFullyQualifiedErrorId + } + } + + Context "Compress-Archive - Parameter validation test cases" { + + It "Validate errors from Compress-Archive with NULL & EMPTY values for Path, LiteralPath, DestinationPath, CompressionLevel parameters" { + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "$TestDrive/SampleSingleFile.zip" + + CompressArchivePathParameterSetValidator $null $destinationPath + CompressArchivePathParameterSetValidator $sourcePath $null + CompressArchivePathParameterSetValidator $null $null + + CompressArchivePathParameterSetValidator "" $destinationPath + CompressArchivePathParameterSetValidator $sourcePath "" + CompressArchivePathParameterSetValidator "" "" + + CompressArchivePathParameterSetValidator $null $null "NoCompression" + + CompressArchiveLiteralPathParameterSetValidator $null $destinationPath + CompressArchiveLiteralPathParameterSetValidator $sourcePath $null + CompressArchiveLiteralPathParameterSetValidator $null $null + + CompressArchiveLiteralPathParameterSetValidator "" $destinationPath + CompressArchiveLiteralPathParameterSetValidator $sourcePath "" + CompressArchiveLiteralPathParameterSetValidator "" "" + + CompressArchiveLiteralPathParameterSetValidator $null $null "NoCompression" + + CompressArchiveLiteralPathParameterSetValidator $sourcePath $destinationPath $null + CompressArchiveLiteralPathParameterSetValidator $sourcePath $destinationPath "" + } + + It "Validate errors from Compress-Archive when invalid path (non-existing path / non-filesystem path) is supplied for Path or LiteralPath parameters" { + CompressArchiveInValidPathValidator "$TestDrive/InvalidPath" $TestDrive "$TestDrive/InvalidPath" "ArchiveCmdletPathNotFound,Compress-Archive" + if ( ! $IsCore ) { + CompressArchiveInValidPathValidator "HKLM:/SOFTWARE" $TestDrive "HKLM:/SOFTWARE" "PathNotFound,Compress-Archive" + } + CompressArchiveInValidPathValidator "$TestDrive" "$TestDrive/NonExistingDirectory/sample.zip" "$TestDrive/NonExistingDirectory/sample.zip" "ArchiveCmdletPathNotFound,Compress-Archive" + + $path = @("$TestDrive", "$TestDrive/InvalidPath") + CompressArchiveInValidPathValidator $path $TestDrive "$TestDrive/InvalidPath" "ArchiveCmdletPathNotFound,Compress-Archive" + + if ( ! $IsCore ) { + $path = @("$TestDrive", "HKLM:/SOFTWARE") + CompressArchiveInValidPathValidator $path $TestDrive "HKLM:/SOFTWARE" "PathNotFound,Compress-Archive" + } + + $invalidUnZipFileFormat = "$TestDrive/Sample.unzip" + CompressArchiveInValidArchiveFileExtensionValidator $TestDrive "$invalidUnZipFileFormat" ".unzip" + + $invalidcabZipFileFormat = "$TestDrive/Sample.cab" + CompressArchiveInValidArchiveFileExtensionValidator $TestDrive "$invalidcabZipFileFormat" ".cab" + } + + It "Validate error from Compress-Archive when archive file already exists and -Update parameter is not specified" { + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "$TestDrive/ValidateErrorWhenUpdateNotSpecified.zip" + + try + { + "Some Data" > $destinationPath + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + throw "Failed to validate that an archive file format $destinationPath already exists and -Update switch parameter is not specified while running Compress-Archive command." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "ArchiveFileExists,Compress-Archive" + } + } + + It "Validate error from Compress-Archive when duplicate paths are supplied as input to Path parameter" { + $sourcePath = @( + "$TestDrive/SourceDir/Sample-1.txt", + "$TestDrive/SourceDir/Sample-1.txt") + $destinationPath = "$TestDrive/DuplicatePaths.zip" + + try + { + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + throw "Failed to detect that duplicate Path $sourcePath is supplied as input to Path parameter." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "DuplicatePathFound,Compress-Archive" + } + } + + It "Validate error from Compress-Archive when duplicate paths are supplied as input to LiteralPath parameter" { + $sourcePath = @( + "$TestDrive/SourceDir/Sample-1.txt", + "$TestDrive/SourceDir/Sample-1.txt") + $destinationPath = "$TestDrive/DuplicatePaths.zip" + + try + { + Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath + throw "Failed to detect that duplicate Path $sourcePath is supplied as input to LiteralPath parameter." + } + catch + { + $_.FullyQualifiedErrorId | Should Be "DuplicatePathFound,Compress-Archive" + } + } + + It "Validate that relative path can be specified as Path parameter of Compress-Archive cmdlet" { + $sourcePath = "./SourceDir" + $destinationPath = "RelativePathForPathParameter.zip" + try { + push-location $TESTDRIVE + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + finally { + Pop-Location + } + } + It "Validate that relative path can be specified as LiteralPath parameter of Compress-Archive cmdlet" { + $sourcePath = "./SourceDir" + $destinationPath = "RelativePathForLiteralPathParameter.zip" + try { + push-location $TESTDRIVE + Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + finally { + Pop-Location + } + } + It "Validate that relative path can be specified as DestinationPath parameter of Compress-Archive cmdlet" { + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "./RelativePathForDestinationPathParameter.zip" + try { + push-location $TESTDRIVE + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + finally { + Pop-Location + } + } + } + + Context "Compress-Archive - functional test cases" { + It "Validate that a single file can be compressed using Compress-Archive cmdlet" { + $sourcePath = [io.path]::Combine("$TestDrive","SourceDir","ChildDir-1","Sample-3.txt") + $destinationPath = [io.path]::Combine("$TestDrive","SampleSingleFile.zip") + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + $destinationPath | Should Exist + } + # This test requires a fix in PS5 to support reading paths with square bracket + It "Validate that Compress-Archive cmdlet can accept LiteralPath parameter with Special Characters" -skip:($PSVersionTable.psversion -lt "5.0") { + $sourcePath = "$TestDrive/SourceDir/ChildDir-1/Sample[]File.txt" + "Some Random Content" | Out-File -LiteralPath $sourcePath + $destinationPath = "$TestDrive/SampleSingleFileWithSpecialCharacters.zip" + try + { + Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath + $destinationPath | Should Exist + } + finally + { + get-item -literalPath $sourcePath | remove-Item -force + # Remove-Item -LiteralPath $sourcePath -Force + } + } + It "Validate that Compress-Archive cmdlet errors out when DestinationPath resolves to multiple locations" { + + New-Item $TestDrive/SampleDir/Child-1 -Type Directory -Force | Out-Null + New-Item $TestDrive/SampleDir/Child-2 -Type Directory -Force | Out-Null + New-Item $TestDrive/SampleDir/Test.txt -Type File -Force | Out-Null + + $destinationPath = "$TestDrive/SampleDir/Child-*/SampleChidArchive.zip" + $sourcePath = "$TestDrive/SampleDir/Test.txt" + try + { + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + throw "Failed to detect that destination $destinationPath can resolve to multiple paths" + } + catch + { + $_.FullyQualifiedErrorId | Should Be "InvalidArchiveFilePath,Compress-Archive" + } + finally + { + Remove-Item -LiteralPath $TestDrive/SampleDir -Force -Recurse + } + } + It "Validate that Compress-Archive cmdlet works when DestinationPath has wild card pattern and resolves to a single valid path" { + + New-Item $TestDrive/SampleDir/Child-1 -Type Directory -Force | Out-Null + New-Item $TestDrive/SampleDir/Test.txt -Type File -Force | Out-Null + + $destinationPath = "$TestDrive/SampleDir/Child-*/SampleChidArchive.zip" + $sourcePath = "$TestDrive/SampleDir/Test.txt" + try + { + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + $destinationPath | Should Exist + } + finally + { + Remove-Item -LiteralPath $TestDrive/SampleDir -Force -Recurse + } + } + # This test requires a fix in PS5 to support reading paths with square bracket + It "Validate that Compress-Archive cmdlet can accept LiteralPath parameter for a directory with Special Characters in the directory name" -skip:($PSVersionTable.psversion -lt "5.0") { + $sourcePath = "$TestDrive/Source[]Dir/ChildDir[]-1" + New-Item $sourcePath -Type Directory | Out-Null + "Some Random Content" | Out-File -LiteralPath "$sourcePath/Sample[]File.txt" + $destinationPath = "$TestDrive/SampleDirWithSpecialCharacters.zip" + try + { + Compress-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath + $destinationPath | Should Exist + } + finally + { + get-item -LiteralPath $sourcePath | Remove-Item -Force -Recurse + # Remove-Item -LiteralPath $sourcePath -Force -Recurse + } + } + It "Validate that Compress-Archive cmdlet can accept DestinationPath parameter with Special Characters" { + $sourcePath = "$TestDrive/SourceDir/ChildDir-1/Sample-3.txt" + $destinationPath = "$TestDrive/Sample[]SingleFile.zip" + try + { + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path -LiteralPath $destinationPath | Should Be $true + } + finally + { + Get-Item -LiteralPath $destinationPath | Remove-Item -Force + # Remove-Item -LiteralPath $destinationPath -Force + } + } + It "Validate that Source Path can be at SystemDrive location" -skip:($IsCore) { + $sourcePath = "$env:SystemDrive/SourceDir" + $destinationPath = "$TestDrive/SampleFromSystemDrive.zip" + New-Item $sourcePath -Type Directory | Out-Null + "Some Data" | Out-File -FilePath $sourcePath/SampleSourceFileForArchive.txt + try + { + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + finally + { + remove-item "$sourcePath" -Force -Recurse -ErrorAction SilentlyContinue + } + } + It "Validate that multiple files can be compressed using Compress-Archive cmdlet" { + $sourcePath = @( + "$TestDrive/SourceDir/ChildDir-1/Sample-3.txt", + "$TestDrive/SourceDir/ChildDir-1/Sample-4.txt", + "$TestDrive/SourceDir/ChildDir-2/Sample-5.txt", + "$TestDrive/SourceDir/ChildDir-2/Sample-6.txt") + $destinationPath = "$TestDrive/SampleMultipleFiles.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + It "Validate that multiple files and directories can be compressed using Compress-Archive cmdlet" { + $sourcePath = @( + "$TestDrive/SourceDir/Sample-1.txt", + "$TestDrive/SourceDir/Sample-2.txt", + "$TestDrive/SourceDir/ChildDir-1", + "$TestDrive/SourceDir/ChildDir-2") + $destinationPath = "$TestDrive/SampleMultipleFilesAndDirs.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + It "Validate that a single directory can be compressed using Compress-Archive cmdlet" { + $sourcePath = @("$TestDrive/SourceDir/ChildDir-1") + $destinationPath = "$TestDrive/SampleSingleDir.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + It "Validate that a single directory with multiple files and subdirectories can be compressed using Compress-Archive cmdlet" { + $sourcePath = @("$TestDrive/SourceDir") + $destinationPath = "$TestDrive/SampleSubTree.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + It "Validate that a single directory & multiple files can be compressed using Compress-Archive cmdlet" { + $sourcePath = @( + "$TestDrive/SourceDir/ChildDir-1", + "$TestDrive/SourceDir/Sample-1.txt", + "$TestDrive/SourceDir/Sample-2.txt") + $destinationPath = "$TestDrive/SampleMultipleFilesAndSingleDir.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + + It "Validate that if .zip extension is not supplied as input to DestinationPath parameter, then .zip extension is appended" { + $sourcePath = @("$TestDrive/SourceDir") + $destinationPath = "$TestDrive/SampleNoExtension.zip" + $destinationWithoutExtensionPath = "$TestDrive/SampleNoExtension" + Compress-Archive -Path $sourcePath -DestinationPath $destinationWithoutExtensionPath + Test-Path $destinationPath | Should Be $true + } + + It "Validate that -Update parameter makes Compress-Archive to not throw an error if archive file already exists" { + $sourcePath = @("$TestDrive/SourceDir") + $destinationPath = "$TestDrive/SampleUpdateTest.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update + Test-Path $destinationPath | Should Be $true + } + It "Validate -Update parameter by adding a new file to an existing archive file" { + $sourcePath = @("$TestDrive/SourceDir/ChildDir-1") + $destinationPath = "$TestDrive/SampleUpdateAdd1File.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + New-Item $TestDrive/SourceDir/ChildDir-1/Sample-AddedNewFile.txt -Type File | Out-Null + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update + Test-Path $destinationPath | Should Be $true + Validate-ArchiveEntryCount -path $destinationPath -expectedEntryCount 3 + } + + It "Validate that all CompressionLevel values can be used with Compress-Archive cmdlet" { + $sourcePath = "$TestDrive/SourceDir/Sample-1.txt" + + $destinationPath = "$TestDrive/FastestCompressionLevel.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel Fastest + Test-Path $destinationPath | Should Be $true + + $destinationPath = "$TestDrive/OptimalCompressionLevel.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel Optimal + Test-Path $destinationPath | Should Be $true + + $destinationPath = "$TestDrive/NoCompressionCompressionLevel.zip" + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -CompressionLevel NoCompression + Test-Path $destinationPath | Should Be $true + } + + It "Validate that -Update parameter is modifying a file that already exists in the archive file" { + $filePath = "$TestDrive/SourceDir/ChildDir-1/Sample-3.txt" + + $initialContent = "Initial Content" + $modifiedContent = "Modified Content" + + $initialContent | Set-Content $filePath + + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "$TestDrive/UpdatingModifiedFile.zip" + + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $True + + $modifiedContent | Set-Content $filePath + + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath -Update + Test-Path $destinationPath | Should Be $True + + ArchiveFileEntryContentValidator "$destinationPath" ([io.path]::Combine("SourceDir","ChildDir-1","Sample-3.txt")) $modifiedContent + } + + It "Validate Compress-Archive cmdlet in pipleline scenario" { + $destinationPath = "$TestDrive/CompressArchiveFromPipeline.zip" + + # Piping a single file path to Compress-Archive + dir -Path $TestDrive/SourceDir/Sample-1.txt | Compress-Archive -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $True + + # Piping a string directory path to Compress-Archive + "$TestDrive/SourceDir/ChildDir-2" | Compress-Archive -DestinationPath $destinationPath -Update + Test-Path $destinationPath | Should Be $True + + # Piping the output of Get-ChildItem to Compress-Archive + dir "$TestDrive/SourceDir" -Recurse | Compress-Archive -DestinationPath $destinationPath -Update + Test-Path $destinationPath | Should Be $True + } + + It "Validate that Compress-Archive works on ReadOnly files" { + $sourcePath = "$TestDrive/ReadOnlyFile.txt" + $destinationPath = "$TestDrive/TestForReadOnlyFile.zip" + + "Some Content" | Out-File -FilePath $sourcePath + $createdItem = Get-Item $sourcePath + $createdItem.Attributes = 'ReadOnly' + + Compress-Archive -Path $sourcePath -DestinationPath $destinationPath + Test-Path $destinationPath | Should Be $true + } + + It "Validate that Compress-Archive generates Verbose messages" { + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "$TestDrive/Compress-Archive generates VerboseMessages.zip" + + try + { + $ps=[PowerShell]::Create() + $ps.Streams.Error.Clear() + $ps.Streams.Verbose.Clear() + $script = "Import-Module Microsoft.PowerShell.Archive; Compress-Archive -Path $sourcePath -DestinationPath `"$destinationPath`" -CompressionLevel Fastest -Verbose" + $ps.AddScript($script) + $ps.Invoke() + + $ps.Streams.Verbose.Count -gt 0 | Should Be $True + $ps.Streams.Error.Count | Should Be 0 + } + finally + { + $ps.Dispose() + } + } + } + + Context "Expand-Archive - Parameter validation test cases" { + It "Validate non existing archive -Path trows expected error message" { + $sourcePath = "$TestDrive/SourceDir" + $destinationPath = "$TestDrive/ExpandedArchive" + try + { + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath + throw "Expand-Archive succeeded for non existing archive path" + } + catch + { + $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" + } + } + + It "Validate errors from Expand-Archive with NULL & EMPTY values for Path, LiteralPath, DestinationPath parameters" { + ExpandArchiveInvalidParameterValidator $false $null "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $false $null $null "ParameterArgumentValidationError,Expand-Archive" + + ExpandArchiveInvalidParameterValidator $false "$TestDrive/SourceDir" $null "ParameterArgumentTransformationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $false "" "$TestDrive/SourceDir" "ParameterArgumentTransformationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $false "$TestDrive/SourceDir" "" "ParameterArgumentTransformationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $false "" "" "ParameterArgumentTransformationError,Expand-Archive" + + ExpandArchiveInvalidParameterValidator $true $null "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true $null $null "ParameterArgumentValidationError,Expand-Archive" + + ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" $null "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "" "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" "" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "" "" "ParameterArgumentValidationError,Expand-Archive" + + ExpandArchiveInvalidParameterValidator $true $null "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true $null $null "ParameterArgumentValidationError,Expand-Archive" + + ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" $null "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "" "$TestDrive/SourceDir" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "$TestDrive/SourceDir" "" "ParameterArgumentValidationError,Expand-Archive" + ExpandArchiveInvalidParameterValidator $true "" "" "ParameterArgumentValidationError,Expand-Archive" + } + + It "Validate errors from Expand-Archive when invalid path (non-existing path / non-filesystem path) is supplied for Path or LiteralPath parameters" { + try { Expand-Archive -Path "$TestDrive/NonExistingArchive" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "ArchiveCmdletPathNotFound,Expand-Archive" } + + if ( ! $IsCore ) { + try { Expand-Archive -Path "HKLM:/SOFTWARE" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" } + } + + try { Expand-Archive -LiteralPath "$TestDrive/NonExistingArchive" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "ArchiveCmdletPathNotFound,Expand-Archive" } + + if ( ! $IsCore ) { + try { Expand-Archive -LiteralPath "HKLM:/SOFTWARE" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" } + } + } + + It "Validate error from Expand-Archive when invalid path (non-existing path / non-filesystem path) is supplied for DestinationPath parameter" { + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + # $destinationPath = "HKLM:/SOFTWARE" + $destinationPath = "Variable:/" + + try { Expand-Archive -Path $sourcePath -DestinationPath $destinationPath; throw "Expand-Archive did NOT throw expected error" } + catch { $_.FullyQualifiedErrorId | Should Be "InvalidDirectoryPath,Expand-Archive" } + } + } + + Context "Expand-Archive - functional test cases" { + It "Validate basic Expand-Archive scenario" { + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $content = "Some Data" + $destinationPath = "$TestDrive/DestDirForBasicExpand" + $files = @("Sample-1.txt", "Sample-2.txt") + + # The files in "$TestDrive/SamplePreCreatedArchive.zip" are precreated. + $fileCreationTimeStamp = Get-Date -Year 2014 -Month 6 -Day 13 -Hour 15 -Minute 50 -Second 20 -Millisecond 0 + + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath + foreach($currentFile in $files) + { + $expandedFile = Join-Path $destinationPath -ChildPath $currentFile + Test-Path $expandedFile | Should Be $True + + # We are validating to make sure that time stamps are preserved in the + # compressed archive are reflected back when the file is expanded. + (dir $expandedFile).LastWriteTime.CompareTo($fileCreationTimeStamp) | Should Be 0 + + Get-Content $expandedFile | Should Be $content + } + } + It "Validate that Expand-Archive cmdlet errors out when DestinationPath resolves to multiple locations" { + $testbasename = "TargetDir" + setup -d "$testbasename" + setup -d "$testbasename/Child-1" + setup -d "$testbasename/Child-2" + + $destinationPath = [io.path]::Combine("$TestDrive","$testbasename","Child-*") + $sourcePath = join-path "$TestDrive" "SamplePreCreatedArchive.zip" + try + { + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath + throw "Failed to detect that destination $destinationPath can resolve to multiple paths" + } + catch + { + $_.FullyQualifiedErrorId | Should Be "InvalidDestinationPath,Expand-Archive" + } + finally + { + Remove-Item -LiteralPath "$TestDrive/$testbasename" -Force -Recurse + } + } + It "Validate that Expand-Archive cmdlet works when DestinationPath resolves has wild card pattern and resolves to a single valid path" { + $testbasename = "TargetDir" + setup -d "$testbasename" + setup -d "$testbasename/Child-1" + + $destinationPath = [io.path]::Combine("$TestDrive","$testbasename","Child-*") + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + try + { + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath + $expandedFiles = Get-ChildItem $destinationPath -Recurse + $expandedFiles.Length | Should BeGreaterThan 1 + } + finally + { + Remove-Item -LiteralPath "$TestDrive/$testbasename" -Force -Recurse + } + } + It "Validate Expand-Archive scenario where DestinationPath has Special Characters" { + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $content = "Some Data" + $destinationPath = "$TestDrive/DestDir[]Expand" + $files = @("Sample-1.txt", "Sample-2.txt") + + # The files in "$TestDrive/SamplePreCreatedArchive.zip" are precreated. + $fileCreationTimeStamp = Get-Date -Year 2014 -Month 6 -Day 13 -Hour 15 -Minute 50 -Second 20 -Millisecond 0 + + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath + foreach($currentFile in $files) + { + $expandedFile = Join-Path $destinationPath -ChildPath $currentFile + Test-Path -LiteralPath $expandedFile | Should Be $True + + # We are validating to make sure that time stamps are preserved in the + # compressed archive are reflected back when the file is expanded. + (dir -LiteralPath $expandedFile).LastWriteTime.CompareTo($fileCreationTimeStamp) | Should Be 0 + + Get-Content -LiteralPath $expandedFile | Should Be $content + } + } + It "Invoke Expand-Archive with relative path in Path parameter and -Force parameter" { + $sourcePath = "./SamplePreCreatedArchive.zip" + $destinationPath = "$TestDrive/SomeOtherNonExistingDir/Path" + try + { + Push-Location $TestDrive + + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Force + $expandedFiles = Get-ChildItem $destinationPath -Recurse + $expandedFiles.Length | Should Be 2 + } + finally + { + Pop-Location + } + } + + It "Invoke Expand-Archive with relative path in LiteralPath parameter and -Force parameter" { + $sourcePath = "./SamplePreCreatedArchive.zip" + $destinationPath = "$TestDrive/SomeOtherNonExistingDir/LiteralPath" + try + { + Push-Location $TestDrive + + Expand-Archive -LiteralPath $sourcePath -DestinationPath $destinationPath -Force + $expandedFiles = Get-ChildItem $destinationPath -Recurse + $expandedFiles.Length | Should Be 2 + } + finally + { + Pop-Location + } + } + + It "Invoke Expand-Archive with non-existing relative directory in DestinationPath parameter and -Force parameter" { + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $destinationPath = "./SomeOtherNonExistingDir/DestinationPath" + try + { + Push-Location $TestDrive + + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Force + $expandedFiles = Get-ChildItem $destinationPath -Recurse + $expandedFiles.Length | Should Be 2 + } + finally + { + Pop-Location + } + } + + It "Invoke Expand-Archive with unsupported archive format" { + $sourcePath = "$TestDrive/Sample.cab" + $destinationPath = "$TestDrive/UnsupportedArchiveFormatDir" + try + { + Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Force + throw "Failed to detect unsupported archive format at $sourcePath" + } + catch + { + $_.FullyQualifiedErrorId | Should Be "NotSupportedArchiveFileExtension,Expand-Archive" + } + } + + It "Invoke Expand-Archive with archive file containing multiple files, directories with subdirectories and empty directories" { + $sourcePath = "$TestDrive/SourceDir" + $archivePath = "$TestDrive/FileAndDirTreeForExpand.zip" + $destinationPath = "$TestDrive/FileAndDirTree" + $sourceList = dir $sourcePath -Name + + Add-CompressionAssemblies + [System.IO.Compression.ZipFile]::CreateFromDirectory($sourcePath, $archivePath) + + Expand-Archive -Path $archivePath -DestinationPath $destinationPath + $extractedList = dir $destinationPath -Name + + Compare-Object -ReferenceObject $extractedList -DifferenceObject $sourceList -PassThru | Should Be $null + } + + It "Validate Expand-Archive cmdlet in pipleline scenario" { + $sourcePath = "$TestDrive/SamplePreCreated*.zip" + $destinationPath = "$TestDrive/PipeToExpandArchive" + + $content = "Some Data" + $files = @("Sample-1.txt", "Sample-2.txt") + + dir $sourcePath | Expand-Archive -DestinationPath $destinationPath + + foreach($currentFile in $files) + { + $expandedFile = Join-Path $destinationPath -ChildPath $currentFile + Test-Path $expandedFile | Should Be $True + Get-Content $expandedFile | Should Be $content + } + } + + It "Validate that Expand-Archive generates Verbose messages" { + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $destinationPath = "$TestDrive/VerboseMessagesInExpandArchive" + + try + { + $ps=[PowerShell]::Create() + $ps.Streams.Error.Clear() + $ps.Streams.Verbose.Clear() + $script = "Import-Module Microsoft.PowerShell.Archive; Expand-Archive -Path $sourcePath -DestinationPath $destinationPath -Verbose" + $ps.AddScript($script) + $ps.Invoke() + + $ps.Streams.Verbose.Count -gt 0 | Should Be $True + $ps.Streams.Error.Count | Should Be 0 + } + finally + { + $ps.Dispose() + } + } + + It "Validate that without -Force parameter Expand-Archive generates non-terminating errors without overwriting existing files" { + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $destinationPath = "$TestDrive/NoForceParameterExpandArchive" + + try + { + $ps=[PowerShell]::Create() + $ps.Streams.Error.Clear() + $ps.Streams.Verbose.Clear() + $script = "Import-Module Microsoft.PowerShell.Archive; Expand-Archive -Path $sourcePath -DestinationPath $destinationPath; Expand-Archive -Path $sourcePath -DestinationPath $destinationPath" + $ps.AddScript($script) + $ps.Invoke() + + $ps.Streams.Error.Count -gt 0 | Should Be $True + } + finally + { + $ps.Dispose() + } + } + + It "Validate that without DestinationPath parameter Expand-Archive cmdlet succeeds in expanding the archive" { + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $archivePath = "$TestDrive/NoDestinationPathParameter.zip" + $destinationPath = "$TestDrive/NoDestinationPathParameter" + copy-item $sourcePath $archivePath -Force + + try + { + Push-Location $TestDrive + + Expand-Archive -Path $archivePath + (dir $destinationPath).Count | Should Be 2 + } + finally + { + Pop-Location + } + } + + It "Validate that without DestinationPath parameter Expand-Archive cmdlet succeeds in expanding the archive when destination directory exists" { + $sourcePath = "$TestDrive/SamplePreCreatedArchive.zip" + $archivePath = "$TestDrive/NoDestinationPathParameterDirExists.zip" + $destinationPath = "$TestDrive/NoDestinationPathParameterDirExists" + copy-item $sourcePath $archivePath -Force + New-Item -Path $destinationPath -ItemType Directory | Out-Null + + try + { + Push-Location $TestDrive + + Expand-Archive -Path $archivePath + (dir $destinationPath).Count | Should Be 2 + } + finally + { + Pop-Location + } + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 index 4dd0e2b1b..054e08f1f 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/History.Tests.ps1 @@ -1,64 +1,64 @@ -Describe "History cmdlet test cases" -Tags "CI" { - - It "Tests Invoke-History on a cmdlet that generates output on all streams" { - $streamSpammer = ' - function StreamSpammer - { - [CmdletBinding()] - param() - - Write-Debug "Debug" - Write-Error "Error" - Write-Information "Information" - Write-Progress "Progress" - Write-Verbose "Verbose" - Write-Warning "Warning" - "Output" - } - - $informationPreference = "Continue" - $debugPreference = "Continue" - $verbosePreference = "Continue" - ' - - $invocationSettings = New-Object System.Management.Automation.PSInvocationSettings - $invocationSettings.AddToHistory = $true - $ps = [PowerShell]::Create() - $null = $ps.AddScript($streamSpammer).Invoke() - $ps.Commands.Clear() - $null = $ps.AddScript("StreamSpammer"); - $null = $ps.Invoke($null, $invocationSettings) - $ps.Commands.Clear() - $null = $ps.AddScript("Invoke-History -id 1") - $result = $ps.Invoke($null, $invocationSettings) - $outputCount = $( - $ps.Streams.Error; - $ps.Streams.Progress; - $ps.Streams.Verbose; - $ps.Streams.Debug; - $ps.Streams.Warning; - $ps.Streams.Information).Count - $ps.Dispose() - - ## Twice per stream - once for the original invocatgion, and once for the re-invocation - $outputCount | Should be 12 - } - - It "Tests Invoke-History on a private command" { - - $invocationSettings = New-Object System.Management.Automation.PSInvocationSettings - $invocationSettings.AddToHistory = $true - $ps = [PowerShell]::Create() - $null = $ps.AddScript("(Get-Command Get-Process).Visibility = 'Private'").Invoke() - $ps.Commands.Clear() - $null = $ps.AddScript("Get-Process -id $pid") - $null = $ps.Invoke($null, $invocationSettings) - $ps.Commands.Clear() - $null = $ps.AddScript("Invoke-History -id 1") - $result = $ps.Invoke($null, $invocationSettings) - $errorResult = $ps.Streams.Error[0].FullyQualifiedErrorId - $ps.Dispose() - - $errorResult | Should be CommandNotFoundException - } -} +Describe "History cmdlet test cases" -Tags "CI" { + + It "Tests Invoke-History on a cmdlet that generates output on all streams" { + $streamSpammer = ' + function StreamSpammer + { + [CmdletBinding()] + param() + + Write-Debug "Debug" + Write-Error "Error" + Write-Information "Information" + Write-Progress "Progress" + Write-Verbose "Verbose" + Write-Warning "Warning" + "Output" + } + + $informationPreference = "Continue" + $debugPreference = "Continue" + $verbosePreference = "Continue" + ' + + $invocationSettings = New-Object System.Management.Automation.PSInvocationSettings + $invocationSettings.AddToHistory = $true + $ps = [PowerShell]::Create() + $null = $ps.AddScript($streamSpammer).Invoke() + $ps.Commands.Clear() + $null = $ps.AddScript("StreamSpammer"); + $null = $ps.Invoke($null, $invocationSettings) + $ps.Commands.Clear() + $null = $ps.AddScript("Invoke-History -id 1") + $result = $ps.Invoke($null, $invocationSettings) + $outputCount = $( + $ps.Streams.Error; + $ps.Streams.Progress; + $ps.Streams.Verbose; + $ps.Streams.Debug; + $ps.Streams.Warning; + $ps.Streams.Information).Count + $ps.Dispose() + + ## Twice per stream - once for the original invocatgion, and once for the re-invocation + $outputCount | Should be 12 + } + + It "Tests Invoke-History on a private command" { + + $invocationSettings = New-Object System.Management.Automation.PSInvocationSettings + $invocationSettings.AddToHistory = $true + $ps = [PowerShell]::Create() + $null = $ps.AddScript("(Get-Command Get-Process).Visibility = 'Private'").Invoke() + $ps.Commands.Clear() + $null = $ps.AddScript("Get-Process -id $pid") + $null = $ps.Invoke($null, $invocationSettings) + $ps.Commands.Clear() + $null = $ps.AddScript("Invoke-History -id 1") + $result = $ps.Invoke($null, $invocationSettings) + $errorResult = $ps.Streams.Error[0].FullyQualifiedErrorId + $ps.Dispose() + + $errorResult | Should be CommandNotFoundException + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 index 0c99c4270..ce3511946 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/Pester.Commands.Cmdlets.GetCommand.Tests.ps1 @@ -1,52 +1,52 @@ -## -## Copyright (c) Microsoft Corporation, 2015 -## - -Describe "Tests Get-Command with relative paths and wildcards" -Tag "CI" { - - BeforeAll { - # Create temporary EXE command files - $file1 = Setup -f WildCardCommandA.exe -pass - $file2 = Setup -f WildCardCommand[B].exe -pass - #$null = New-Item -ItemType File -Path (Join-Path $TestDrive WildCardCommandA.exe) -ErrorAction Ignore - #$null = New-Item -ItemType File -Path (Join-Path $TestDRive WildCardCommand[B].exe) -ErrorAction Ignore - if ( $IsLinux -or $IsOSX ) { - /bin/chmod 777 "$file1" - /bin/chmod 777 "$file2" - } - } - - It "Test wildcard with drive relative directory path" { - $pathName = Join-Path $TestDrive "WildCardCommandA*" - $driveOffset = $pathName.IndexOf(":") - $pathName = $pathName.Substring($driveOffset + 1) - $result = Get-Command -Name $pathName - $result | Should Not Be $null - $result.Name | Should Be WildCardCommandA.exe - } - - It "Test wildcard with relative directory path" { - push-location $TestDrive - $result = Get-Command -Name .\WildCardCommandA* - pop-location - $result | Should Not Be $null - $result | Should Be WildCardCommandA.exe - } - - It "Test with PowerShell wildcard and relative path" { - push-location $TestDrive - - # This should use the wildcard to find WildCardCommandA.exe - $result = Get-Command -Name .\WildCardCommand[A].exe - $result | Should Not Be $null - $result | Should Be WildCardCommandA.exe - - # This should find the file WildCardCommand[B].exe - $result = Get-Command -Name .\WildCardCommand[B].exe - $result | Should Not Be $null - $result | Should Be WildCardCommand[B].exe - - Pop-Location - } - -} +## +## Copyright (c) Microsoft Corporation, 2015 +## + +Describe "Tests Get-Command with relative paths and wildcards" -Tag "CI" { + + BeforeAll { + # Create temporary EXE command files + $file1 = Setup -f WildCardCommandA.exe -pass + $file2 = Setup -f WildCardCommand[B].exe -pass + #$null = New-Item -ItemType File -Path (Join-Path $TestDrive WildCardCommandA.exe) -ErrorAction Ignore + #$null = New-Item -ItemType File -Path (Join-Path $TestDRive WildCardCommand[B].exe) -ErrorAction Ignore + if ( $IsLinux -or $IsOSX ) { + /bin/chmod 777 "$file1" + /bin/chmod 777 "$file2" + } + } + + It "Test wildcard with drive relative directory path" { + $pathName = Join-Path $TestDrive "WildCardCommandA*" + $driveOffset = $pathName.IndexOf(":") + $pathName = $pathName.Substring($driveOffset + 1) + $result = Get-Command -Name $pathName + $result | Should Not Be $null + $result.Name | Should Be WildCardCommandA.exe + } + + It "Test wildcard with relative directory path" { + push-location $TestDrive + $result = Get-Command -Name .\WildCardCommandA* + pop-location + $result | Should Not Be $null + $result | Should Be WildCardCommandA.exe + } + + It "Test with PowerShell wildcard and relative path" { + push-location $TestDrive + + # This should use the wildcard to find WildCardCommandA.exe + $result = Get-Command -Name .\WildCardCommand[A].exe + $result | Should Not Be $null + $result | Should Be WildCardCommandA.exe + + # This should find the file WildCardCommand[B].exe + $result = Get-Command -Name .\WildCardCommand[B].exe + $result | Should Not Be $null + $result | Should Be WildCardCommand[B].exe + + Pop-Location + } + +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 index dd1c13a73..49f4e7cfa 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 @@ -1,868 +1,868 @@ -# This is a Pester test suite to validate Copy-Item remotely using a remote session. -# -# Copyright (c) Microsoft Corporation, 2015 -# -# - -# If PS Remoting is not available, do not run the suite. -function ShouldRun -{ - if ( $IsCore ) { return $false } - $result = Invoke-Command -ComputerName . -ScriptBlock {1} -ErrorAction SilentlyContinue - return ($result -eq 1) -} - -if (-not (ShouldRun)) -{ - Write-Host "PS Remoting is not available, skipping tests..." -ForegroundColor Cyan - return -} - -Describe "Validate Copy-Item Remotely" -Tags "CI" { - - # Validate a copy item operation. - # $filePath is the source file path - # - function ValidateCopyItemOperation - { - param ([string]$filePath, [string]$destination) - - if (-not $destination) - { - $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") - } - else - { - $fileName = Split-Path $filePath -Leaf - $copiedFilePath = Join-Path $destination $fileName - } - - $copiedFilePath | should Exist - - # Validate file attributes - $originalFile = Get-Item $filePath -Force - $newFile = Get-Item $copiedFilePath -Force - - # Validate file Length - $newFile.Length | should be $originalFile.Length - - # Validate LastWriteTime - $newFile.LastWriteTime | should be $originalFile.LastWriteTime - $newFile.LastWriteTimeUtc | should be $originalFile.LastWriteTimeUtc - - # Validate Attributes - $newFile.Attributes.value__ | Should Be $originalFile.Attributes.value__ - } - - # Validate a copy item operation. - # $filePath is the source file path - # - function ValidateCopyItemOperationForAlternateDataStream - { - param ([string]$filePath, $streamName, $expectedStreamContent) - - $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") - $copiedFilePath | should Exist - (Get-Item $copiedFilePath).Length | should be (Get-Item $filePath).Length - - # Validate the stream - $actualStreamContent = Get-Content -Path $copiedFilePath -Stream $streamName -ea SilentlyContinue - $actualStreamContent | Should Match $expectedStreamContent - } - - BeforeAll { - $s = New-PSSession -ComputerName . -ea SilentlyContinue - if (-not $s) - { - throw "Failed to create PSSession for remote copy operations." - } - - $destinationFolderName = "DestinationDirectory" - $sourceFolderName = "SourceDirectory" - $testDirectory = Join-Path "TestDrive:" "copyItemRemotely" - $destinationDirectory = Join-Path $testDirectory $destinationFolderName - $sourceDirectory = Join-Path $testDirectory $sourceFolderName - - # Creates one txt file - # - function CreateTestFile - { - param ([switch]$setReadOnlyAttribute = $false, [switch]$emptyFile = $false) - - # Create the test directory. - New-Item -Path $sourceDirectory -Force -ItemType Directory | Out-Null - - # Create the file. - $filePath = Join-Path $sourceDirectory "testfileone.txt" - if (-not $emptyFile) - { - "File test content" | Out-File $filePath -Force - } - else - { - "" | Out-File $filePath -Force - } - - if (-not (Test-Path $filePath)) - { - throw "Failed to create test file $filePath." - } - - if ($setReadOnlyAttribute) - { - Set-ItemProperty $filePath -Name IsReadOnly -value $true -Force - } - - return (Get-Item $filePath).FullName - } - - # Create a set of directories and files with the following structure: - # .\copyItemRemotely\SourceDirectory\A\a.txt - # .\copyItemRemotely\SourceDirectory\A\a2.txt - # .\copyItemRemotely\SourceDirectory\rootFile.txt - # .\copyItemRemotely\SourceDirectory\B\b.txt - # .\copyItemRemotely\SourceDirectory\C\D\d.txt - # - function CreateTestDirectory - { - param ([switch]$setReadOnlyAttribute = $false) - - $directoriesToCreate = @() - $directoriesToCreate += "A" - $directoriesToCreate += "B" - $directoriesToCreate += "C\D" - - $filesToCreate = @() - $filesToCreate += "rootFile.txt" - $filesToCreate += "A\a.txt" - $filesToCreate += "A\a2.txt" - $filesToCreate += "B\b.txt" - $filesToCreate += "C\D\d.txt" - - # Create the directories. - foreach ($directory in $directoriesToCreate) - { - $directoryPath = Join-Path $sourceDirectory $directory - New-Item -Path $directoryPath -Force -ItemType Directory | Out-Null - } - - $result = @{ - SourceDirectory = (Get-Item $sourceDirectory).FullName - Files = @() - } - - # Create the files. - foreach ($file in $filesToCreate) - { - $filePath = Join-Path $sourceDirectory $file - $file + "`r`n File test content" | Out-File $filePath -Force - - if (-not (Test-Path $filePath)) - { - throw "Failed to create test file $filePath." - } - - if ($setReadOnlyAttribute) - { - Set-ItemProperty $filePath -Name IsReadOnly -value $true -Force - } - - $result.Files += (Get-Item $filePath).FullName - } - - return $result - } - - function GenerateTestAssembly - { - $assemblyPath = Join-Path $env:TEMP TestModule - $outputPath = Join-Path $assemblyPath TestModule.dll - - if (-not (Test-Path $assemblyPath)) - { - New-Item $assemblyPath -Force -ItemType Directory | Out-Null - } - - if (-not (Test-Path $outputPath)) - { - $code = @" - namespace TestModule - { - using System; - using System.Management.Automation; - - [Cmdlet(VerbsCommon.Get, "TestModule")] - public class TestSameCmdlets : PSCmdlet - { - protected override void ProcessRecord() - { - WriteObject("TestModule"); - } - } - } -"@ - Add-Type -TypeDefinition $code -OutputAssembly $outputPath - } - - $result = @{ - ModuleName = "TestModule" - Path = (Get-Item $outputPath).FullName - } - - return $result - } - - function GetDestinationFolderPath - { - return (Get-Item $destinationDirectory).FullName - } - } - - AfterAll { - Remove-PSSession -Name $s.Name -ea SilentlyContinue - } - - BeforeEach { - <# Ensure we start with an empty test directory. Here is the file structure - - $destinationFolderName = "DestinationDirectory" - $sourceFolderName = "SourceDirectory" - $testDirectory = Join-Path "TestDrive:" "copyItemRemotely" - $destinationDirectory = Join-Path $testDirectory $destinationFolderName - $sourceDirectory = Join-Path $testDirectory $sourceFolderName - #> - - if (test-path $testDirectory) - { - Remove-Item $testDirectory -Force -ea SilentlyContinue -Recurse - } - - # Create testDirectory, and destinationDirectory - New-Item $testDirectory -ItemType Directory -Force | Out-Null - New-Item $destinationDirectory -ItemType Directory -Force | Out-Null - } - - Context "Validate Copy-Item Locally." { - It "Copy-Item -Path $filePath -Destination $destinationFolderPath" { - - $filePath = CreateTestFile - $destinationFolderPath = GetDestinationFolderPath - Copy-Item -Path $filePath -Destination $destinationFolderPath - ValidateCopyItemOperation -filePath $filePath - } - - It "Copy-Item -Path $($testObject.SourceDirectory) -Destination $destinationFolderPath -Recurse" { - - $testObject = CreateTestDirectory - $destinationFolderPath = GetDestinationFolderPath - Copy-Item -Path $testObject.SourceDirectory -Destination $destinationFolderPath -Recurse - foreach ($file in $testObject.Files) - { - $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") - $copiedFilePath | should Exist - } - } - } - - Context "Validate Copy-Item to remote session." { - - It "Copy one file to remote session." { - $filePath = CreateTestFile - $destinationFolderPath = GetDestinationFolderPath - Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath - ValidateCopyItemOperation -filePath $filePath - } - - It "Copy one read only file to remote session." { - - $filePath = CreateTestFile -setReadOnlyAttribute - $destinationFolderPath = GetDestinationFolderPath - Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -Force - ValidateCopyItemOperation -filePath $filePath - } - - It "Copy-Item works for a read only file when '-Force' is not used." { - - $filePath = CreateTestFile -setReadOnlyAttribute - $destinationFolderPath = GetDestinationFolderPath - Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -Verbose - ValidateCopyItemOperation -filePath $filePath - } - - It "Copy one folder to session Recursively" { - - $testObject = CreateTestDirectory - $destinationFolderPath = GetDestinationFolderPath - Copy-Item -Path $testObject.SourceDirectory -ToSession $s -Destination $destinationFolderPath -Recurse - - foreach ($file in $testObject.Files) - { - $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") - $copiedFilePath | should Exist - (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length - } - } - - It "Copy folder with read only files to remote session recursively." { - $testObject = CreateTestDirectory -setReadOnlyAttribute - $destinationFolderPath = GetDestinationFolderPath - Copy-Item -Path $testObject.SourceDirectory -ToSession $s -Destination $destinationFolderPath -Recurse -Force - - foreach ($file in $testObject.Files) - { - $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") - $copiedFilePath | should Exist - (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length - } - } - - It "Copy one file to remote session fails when the remote directory does not exist." { - - $filePath = CreateTestFile - $destinationFolderPath = GetDestinationFolderPath - $destinationFolderPath = Join-Path $destinationFolderPath "A\B\C\D\E" - $expectedFullyQualifiedErrorId = 'RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand' - - try - { - Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -ErrorAction Stop - throw "CodeExecuted" - } - catch - { - $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId - } - } - - It "Copy folder to remote session recursively works even if the target directory does not exist." { - $testObject = CreateTestDirectory -setReadOnlyAttribute - $destinationFolderPath = GetDestinationFolderPath - $destinationFolderPath = Join-Path $destinationFolderPath "FoderThatDoesNotExist" - Copy-Item -Path $testObject.SourceDirectory -ToSession $s -Destination $destinationFolderPath -Recurse -Force - - foreach ($file in $testObject.Files) - { - $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\FoderThatDoesNotExist") - $copiedFilePath | should Exist - (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length - } - } - - It "Copy one empty file to remote session." { - - $filePath = CreateTestFile -emptyFile - $destinationFolderPath = GetDestinationFolderPath - $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") - $copiedFilePath | should Not Exist - Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath - $copiedFilePath | should Exist - (Get-Item $copiedFilePath).Length | should be (Get-Item $filePath).Length - } - - It "Copy-Item to session supports alternate data streams." { - - $filePath = CreateTestFile - $destinationFolderPath = GetDestinationFolderPath - $streamContent = "This content is hidden" - $streamName = "Hidden" - Set-Content -Path $filePath -Value $streamContent -Stream $streamName - Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -Verbose - ValidateCopyItemOperationForAlternateDataStream -filePath $filePath -streamName $streamName -expectedStreamContent $streamContent - } - } - - Context "Validate Copy-Item from remote session." { - - It "Copy one file from remote session." { - - $filePath = CreateTestFile - $destinationFolderPath = GetDestinationFolderPath - $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") - $copiedFilePath | should Not Exist - Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath - ValidateCopyItemOperation -filePath $filePath - } - - It "Copy one empty file from remote session." { - - $filePath = CreateTestFile -emptyFile - $destinationFolderPath = GetDestinationFolderPath - $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") - $copiedFilePath | should Not Exist - Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath - ValidateCopyItemOperation -filePath $filePath - } - - It "Copy folder from remote session recursively." { - - $testObject = CreateTestDirectory - $destinationFolderPath = GetDestinationFolderPath - $files = @(Get-ChildItem $destinationFolderPath -Recurse -Force) - Copy-Item -Path $testObject.SourceDirectory -FromSession $s -Destination $destinationFolderPath -Recurse - - foreach ($file in $testObject.Files) - { - $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") - $copiedFilePath | should Exist - (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length - } - } - - It "Copy one file from remote session fails when the target directory does not exist." { - - $filePath = CreateTestFile - $destinationFolderPath = GetDestinationFolderPath - $destinationFolderPath = Join-Path $destinationFolderPath "A\B\C\D\E" - $expectedFullyQualifiedErrorId = 'CopyItemRemotelyIOError,Microsoft.PowerShell.Commands.CopyItemCommand' - try - { - Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath -ErrorAction Stop - throw "CodeExecuted" - } - catch - { - $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId - } - } - - It "Copy folder from remote session recursively works even if the target directory does not exist." { - - $testObject = CreateTestDirectory - $destinationFolderPath = GetDestinationFolderPath - $destinationFolderPath = Join-Path $destinationFolderPath "FoderThatDoesNotExist" - $files = @(Get-ChildItem $destinationFolderPath -Recurse -Force) - Copy-Item -Path $testObject.SourceDirectory -FromSession $s -Destination $destinationFolderPath -Recurse - - foreach ($file in $testObject.Files) - { - $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\FoderThatDoesNotExist") - $copiedFilePath | should Exist - (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length - } - } - - It "Copy a read only file from a remote session." { - - $filePath = CreateTestFile -setReadOnlyAttribute - $destinationFolderPath = GetDestinationFolderPath - $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") - Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath -Force - ValidateCopyItemOperation -filePath $filePath - } - - It "Copy-Item for a read only file works with no '-force' parameter." { - - $filePath = CreateTestFile -setReadOnlyAttribute - $destinationFolderPath = GetDestinationFolderPath - Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath - ValidateCopyItemOperation -filePath $filePath - } - - It "Copy-Item -FromSession works even when trying to copy an assembly that is currently being used by another process." { - - $testAssembly = GenerateTestAssembly - $destinationFolderPath = GetDestinationFolderPath - Import-Module $testAssembly.Path -Force - try - { - Copy-Item -Path $testAssembly.Path -FromSession $s -Destination $destinationFolderPath - ValidateCopyItemOperation -filePath $testAssembly.Path - } - finally - { - Remove-Module $testAssembly.ModuleName -Force -ea SilentlyContinue - } - } - - It "Copy-Item from session supports alternate data streams." { - - $filePath = CreateTestFile - $destinationFolderPath = GetDestinationFolderPath - $streamContent = "This content is hidden" - $streamName = "Hidden" - Set-Content -Path $filePath -Value $streamContent -Stream $streamName - Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath - ValidateCopyItemOperationForAlternateDataStream -filePath $filePath -streamName $streamName -expectedStreamContent $streamContent - } - } - - Context "Validate Copy-Item Remotely using wildcards" { - - It "Copy-Item from session using wildcards." { - - $testObject = CreateTestDirectory - $destinationFolderPath = GetDestinationFolderPath - $sourcePathWithWildcards = "$($testObject.SourceDirectory)\A\*.txt" - Copy-Item -Path $sourcePathWithWildcards -FromSession $s -Destination $destinationFolderPath -Force - - $sourceFiles = @(Get-Item $sourcePathWithWildcards) - foreach ($file in $sourceFiles) - { - $copiedFilePath = Join-Path $destinationFolderPath (Split-Path $file -Leaf) - $copiedFilePath | Should Exist - (Get-Item $copiedFilePath).Length | Should Be (Get-Item $file).Length - } - } - - It "Copy-Item to session using wildcards." { - - $testObject = CreateTestDirectory - $destinationFolderPath = GetDestinationFolderPath - $sourcePathWithWildcards = "$($testObject.SourceDirectory)\A\*.txt" - Copy-Item -Path $sourcePathWithWildcards -ToSession $s -Destination $destinationFolderPath -Force - - $sourceFiles = @(Get-Item $sourcePathWithWildcards) - foreach ($file in $sourceFiles) - { - $copiedFilePath = Join-Path $destinationFolderPath (Split-Path $file -Leaf) - $copiedFilePath | Should Exist - (Get-Item $copiedFilePath).Length | Should Be (Get-Item $file).Length - } - } - } - - Context "Validate FullyQualifiedErrorIds for remote source and destination paths." { - - BeforeAll { - # Create test file. - $testFilePath = Join-Path "TestDrive:" "testfile.txt" - if (test-path $testFilePath) - { - Remove-Item $testFilePath -Force -ea SilentlyContinue - } - "File test content" | Out-File $testFilePath -Force - } - - function Test-CopyItemError - { - param ($path, $destination, $expectedFullyQualifiedErrorId, $fromSession = $false) - - if ($fromSession) - { - It "Copy-Item FromSession -Path '$path' throws $expectedFullyQualifiedErrorId" { - try - { - Copy-Item -Path $path -FromSession $s -Destination $destination -ErrorAction Stop - throw "CodeExecuted" - } - catch - { - $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId - } - } - } - else - { - It "Copy-Item ToSession -Destination '$path' throws $expectedFullyQualifiedErrorId" { - try - { - Copy-Item -Path $path -ToSession $s -Destination $destination -ErrorAction Stop - throw "CodeExecuted" - } - catch - { - $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId - } - } - } - } - - $invalidSourcePathtestCases = @( - @{ - Path = "HKLM:\SOFTWARE" - Destination = $env:SystemDrive - ExpectedFullyQualifiedErrorId = "NamedParameterNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" - FromSession = $true - } - @{ - Path = ".\Source" - Destination = $env:SystemDrive - ExpectedFullyQualifiedErrorId = "RemotePathIsNotAbsolute,Microsoft.PowerShell.Commands.CopyItemCommand" - FromSession = $true - } - @{ - Path = $env:SystemDrive + "\X\Y\Z" - Destination = $env:SystemDrive + "\A\B\C" - ExpectedFullyQualifiedErrorId = "RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" - FromSession = $true - } - @{ - Path = $null - Destination = $env:SystemDrive - ExpectedFullyQualifiedErrorId = "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.CopyItemCommand" - FromSession = $true - } - @{ - Path = '' - Destination = $env:SystemDrive - ExpectedFullyQualifiedErrorId = "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.CopyItemCommand" - FromSession = $true - } - @{ - Path = "$env:SystemDrive\nonexistdir\*" - Destination = "$env:SystemDrive\psTest" - ExpectedFullyQualifiedErrorId = "RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" - FromSession = $true - } - ) - - foreach ($testCase in $invalidSourcePathtestCases) { - Test-CopyItemError @testCase - } - - $invalidDestinationPathtestCases = @( - @{ - Path = $testFilePath - Destination = ".\Source" - ExpectedFullyQualifiedErrorId = "RemotePathIsNotAbsolute,Microsoft.PowerShell.Commands.CopyItemCommand" - } - @{ - Path = $testFilePath - Destination = $env:SystemDrive + "\X\A\B\C" - ExpectedFullyQualifiedErrorId = "RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" - } - @{ - Path = $testFilePath - Destination = $null - ExpectedFullyQualifiedErrorId = "CopyItemRemoteDestinationIsNullOrEmpty,Microsoft.PowerShell.Commands.CopyItemCommand" - } - @{ - Path = $testFilePath - Destination = "" - ExpectedFullyQualifiedErrorId = "CopyItemRemoteDestinationIsNullOrEmpty,Microsoft.PowerShell.Commands.CopyItemCommand" - } - @{ - Path = "$env:SystemDrive\nonexistdir\*" - Destination = "$env:SystemDrive\psTest" - ExpectedFullyQualifiedErrorId = "PathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" - } - ) - - foreach ($testCase in $invalidDestinationPathtestCases) { - Test-CopyItemError @testCase - } - } -} - -Describe "Validate Copy-Item error for target sessions not in FullLanguageMode." -Tags "Feature" { - - BeforeAll { - - $testDirectory = "TestDrive:\" - - # Create the test file and directories. - $source = "$testDirectory\Source" - $destination = "$testDirectory\Destination" - - New-Item $source -ItemType Directory -Force | Out-Null - New-Item $destination -ItemType Directory -Force | Out-Null - - $testFilePath = Join-Path $source "testfile.txt" - "File test content" | Out-File $testFilePath -Force - - # Keep track of the sessions. - $testSessions = @{} - - # Keep track of the session names to be unregistered. - $sessionToUnregister = @() - - $languageModes = @("ConstrainedLanguage", "NoLanguage", "RestrictedLanguage") - $id = (Get-Random).ToString() - - foreach ($languageMode in $languageModes) - { - $sessionName = $languageMode + "_" + $id - $sessionToUnregister += $sessionName - $configFilePath = Join-Path $testDirectory "test.pssc" - - # Create the session. - Write-Host "Creating pssession with '$languageMode' ..." - New-PSSessionConfigurationFile -Path $configFilePath -SessionType Default -LanguageMode $languageMode - Register-PSSessionConfiguration -Name $sessionName -Path $configFilePath -Force | Out-Null - $testSession = New-PSSession -ConfigurationName $sessionName - - # Validate that the session is opened. - $testSession.State | Should Be "Opened" - - # Add the new session to the list. - $testSessions[$languageMode] = $testSession - - # Remove the pssc file. - Remove-Item $configFilePath -Force -ea SilentlyContinue - } - } - - AfterAll { - - $testSessions.Values | Remove-PSSession -ea SilentlyContinue - - $sessionToUnregister | foreach { - Unregister-PSSessionConfiguration -Name $_ -Force -ea SilentlyContinue - } - } - - foreach ($languageMode in $testSessions.Keys) - { - $session = $testSessions[$languageMode] - - It "Copy-Item throws 'SessionIsNotInFullLanguageMode' error for a session in '$languageMode'" { - - # FromSession - try - { - Copy-Item -Path $testFilePath -FromSession $session -Destination $destination -Force -Verbose -ea Stop - throw "CodeExecuted" - } - catch - { - $_.FullyQualifiedErrorId | should be "SessionIsNotInFullLanguageMode,Microsoft.PowerShell.Commands.CopyItemCommand" - } - - # ToSession - try - { - Copy-Item -Path $testFilePath -ToSession $session -Destination $destination -Force -Verbose -ea Stop - throw "CodeExecuted" - } - catch - { - $_.FullyQualifiedErrorId | should be "SessionIsNotInFullLanguageMode,Microsoft.PowerShell.Commands.CopyItemCommand" - } - } - } -} - -Describe "Copy-Item can use Recurse and Exclude together" -Tags "Feature" { - - Context "Local and Remote Tests" { - - BeforeAll { - $s = New-PSSession -ComputerName . -ea SilentlyContinue - if (-not $s) - { - throw "Failed to create PSSession for remote copy operations." - } - - $null = New-Item -ItemType Directory -Path "TestDrive:\Parent\Sub" - $null = New-Item -Path "TestDrive:\Parent\p1.txt" -Value "test" - $null = New-Item -Path "TestDrive:\Parent\p2.txt" -Value "test" - $null = New-Item -Path "TestDrive:\Parent\s4.txt" -Value "test" - $null = New-Item -Path "TestDrive:\Parent\Sub\s1.txt" -Value "test" - $null = New-Item -Path "TestDrive:\Parent\Sub\s2.txt" -Value "test" - $null = New-Item -Path "TestDrive:\Parent\Sub\s3.txt" -Value "test" - $null = New-Item -Path "TestDrive:\Parent\Sub\p3.txt" -Value "testcl" - } - - It "can exclude files at sub directory" { - Copy-Item -Path TestDrive:\Parent\* -Recurse -Exclude s*.txt -Destination TestDrive:\Temp -Force - $copiedFiles = Get-ChildItem -Recurse -Path TestDrive:\Temp - $copiedFiles.Count | Should Be 3 - } - - It "can exclude files at sub directory to a session" { - Copy-Item -Path TestDrive:\Parent\* -Recurse -Exclude s*.txt -Destination $TestDrive\Temp2 -Force -ToSession $s - $copiedFiles = Get-ChildItem -Recurse -Path TestDrive:\Temp - $copiedFiles.Count | Should Be 3 - } - - It "can exclude files at sub directory from a session" { - Copy-Item -Path $TestDrive\Parent\* -Recurse -Exclude s*.txt -Destination TestDrive:\Temp3 -FromSession $s - $copiedFiles = Get-ChildItem -Recurse -Path TestDrive:\Temp2 - $copiedFiles.Count | Should Be 3 - } - - AfterAll { - Remove-PSSession -Session $s -ErrorAction SilentlyContinue - } - } -} - -Describe "Copy-Item remotely bug fixes" -Tags "Feature" { - - BeforeAll { - $s = New-PSSession -ComputerName . -ErrorAction SilentlyContinue - if (-not $s) - { - throw "Failed to create PSSession for remote copy operations." - } - - $originalContent = "test file 1 - Source" - $newContent = "This is some new content" - - $null = New-Item -ItemType Directory -Path "TestDrive:\Source" - $null = New-Item -ItemType Directory -Path "TestDrive:\Destination" - } - - AfterAll { - Remove-PSSession -Session $s -ErrorAction SilentlyContinue - } - - BeforeEach { - - # Create the same file in the source and destination - Set-Content -Path "TestDrive:\Source\testFile1.txt" -Value $originalContent -Force - Set-Content -Path "TestDrive:\Destination\testFile1.txt" -Value $originalContent -Force - } - - Context "Copy-Item remotely overwrites a destination file if it exists." { - - BeforeEach { - - # Overwrite the source file - Set-Content -Path "TestDrive:\Source\testFile1.txt" -Value $newContent - } - - It "Copy item -tosession overwrites the content of an existing file." { - - # Copy file to session - Copy-Item -Path "TestDrive:\Source\testFile1.txt" -Destination "$TestDrive\Destination\testFile1.txt" -ToSession $s - - # Validate the the file was overwritten - $fileContent = Get-Content "TestDrive:\Destination\testFile1.txt" -ea SilentlyContinue -Raw - $fileContent | Should Match $newContent - } - - It "Copy item -fromsession overwrites the content of an existing file." { - - # Copy file to session - Copy-Item -Path "$TestDrive\Source\testFile1.txt" -Destination "TestDrive:\Destination\testFile1.txt" -FromSession $s - - # Validate the the file was overwritten - $fileContent = Get-Content "TestDrive:\Destination\testFile1.txt" -ea SilentlyContinue -Raw - $fileContent | Should Match $newContent - } - } - - Context "Copy-Item remotely creates a destination file if it does not exist." { - - BeforeEach { - - if (Test-Path "TestDrive:\AnotherDestination") - { - Remove-Item "TestDrive:\AnotherDestination" -Force -Recurse -ea SilentlyContinue - } - $null = New-Item -ItemType Directory -Path "TestDrive:\AnotherDestination" - - # Ensure the file does not exist - "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" | Should Not Exist - } - - It "Copy-Item -tosession creates the file if it does not exist on the remote destination." { - - # Copy file to session - Copy-Item -Path "TestDrive:\Source\testFile1.txt" -Destination "$TestDrive\AnotherDestination\FileThatDoesNotExist.txt" -ToSession $s - - # Verify that the file was created - "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" | Should Exist - } - - It "Copy-Item -fromsession creates the file if it does not exist on the local machine." { - - # Copy file from session - Copy-Item -Path "$TestDrive\Source\testFile1.txt" -Destination "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" -FromSession $s - - # Verify that the file was created - "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" | Should Exist - } - } -} +# This is a Pester test suite to validate Copy-Item remotely using a remote session. +# +# Copyright (c) Microsoft Corporation, 2015 +# +# + +# If PS Remoting is not available, do not run the suite. +function ShouldRun +{ + if ( $IsCore ) { return $false } + $result = Invoke-Command -ComputerName . -ScriptBlock {1} -ErrorAction SilentlyContinue + return ($result -eq 1) +} + +if (-not (ShouldRun)) +{ + Write-Host "PS Remoting is not available, skipping tests..." -ForegroundColor Cyan + return +} + +Describe "Validate Copy-Item Remotely" -Tags "CI" { + + # Validate a copy item operation. + # $filePath is the source file path + # + function ValidateCopyItemOperation + { + param ([string]$filePath, [string]$destination) + + if (-not $destination) + { + $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") + } + else + { + $fileName = Split-Path $filePath -Leaf + $copiedFilePath = Join-Path $destination $fileName + } + + $copiedFilePath | should Exist + + # Validate file attributes + $originalFile = Get-Item $filePath -Force + $newFile = Get-Item $copiedFilePath -Force + + # Validate file Length + $newFile.Length | should be $originalFile.Length + + # Validate LastWriteTime + $newFile.LastWriteTime | should be $originalFile.LastWriteTime + $newFile.LastWriteTimeUtc | should be $originalFile.LastWriteTimeUtc + + # Validate Attributes + $newFile.Attributes.value__ | Should Be $originalFile.Attributes.value__ + } + + # Validate a copy item operation. + # $filePath is the source file path + # + function ValidateCopyItemOperationForAlternateDataStream + { + param ([string]$filePath, $streamName, $expectedStreamContent) + + $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $filePath).Length + + # Validate the stream + $actualStreamContent = Get-Content -Path $copiedFilePath -Stream $streamName -ea SilentlyContinue + $actualStreamContent | Should Match $expectedStreamContent + } + + BeforeAll { + $s = New-PSSession -ComputerName . -ea SilentlyContinue + if (-not $s) + { + throw "Failed to create PSSession for remote copy operations." + } + + $destinationFolderName = "DestinationDirectory" + $sourceFolderName = "SourceDirectory" + $testDirectory = Join-Path "TestDrive:" "copyItemRemotely" + $destinationDirectory = Join-Path $testDirectory $destinationFolderName + $sourceDirectory = Join-Path $testDirectory $sourceFolderName + + # Creates one txt file + # + function CreateTestFile + { + param ([switch]$setReadOnlyAttribute = $false, [switch]$emptyFile = $false) + + # Create the test directory. + New-Item -Path $sourceDirectory -Force -ItemType Directory | Out-Null + + # Create the file. + $filePath = Join-Path $sourceDirectory "testfileone.txt" + if (-not $emptyFile) + { + "File test content" | Out-File $filePath -Force + } + else + { + "" | Out-File $filePath -Force + } + + if (-not (Test-Path $filePath)) + { + throw "Failed to create test file $filePath." + } + + if ($setReadOnlyAttribute) + { + Set-ItemProperty $filePath -Name IsReadOnly -value $true -Force + } + + return (Get-Item $filePath).FullName + } + + # Create a set of directories and files with the following structure: + # .\copyItemRemotely\SourceDirectory\A\a.txt + # .\copyItemRemotely\SourceDirectory\A\a2.txt + # .\copyItemRemotely\SourceDirectory\rootFile.txt + # .\copyItemRemotely\SourceDirectory\B\b.txt + # .\copyItemRemotely\SourceDirectory\C\D\d.txt + # + function CreateTestDirectory + { + param ([switch]$setReadOnlyAttribute = $false) + + $directoriesToCreate = @() + $directoriesToCreate += "A" + $directoriesToCreate += "B" + $directoriesToCreate += "C\D" + + $filesToCreate = @() + $filesToCreate += "rootFile.txt" + $filesToCreate += "A\a.txt" + $filesToCreate += "A\a2.txt" + $filesToCreate += "B\b.txt" + $filesToCreate += "C\D\d.txt" + + # Create the directories. + foreach ($directory in $directoriesToCreate) + { + $directoryPath = Join-Path $sourceDirectory $directory + New-Item -Path $directoryPath -Force -ItemType Directory | Out-Null + } + + $result = @{ + SourceDirectory = (Get-Item $sourceDirectory).FullName + Files = @() + } + + # Create the files. + foreach ($file in $filesToCreate) + { + $filePath = Join-Path $sourceDirectory $file + $file + "`r`n File test content" | Out-File $filePath -Force + + if (-not (Test-Path $filePath)) + { + throw "Failed to create test file $filePath." + } + + if ($setReadOnlyAttribute) + { + Set-ItemProperty $filePath -Name IsReadOnly -value $true -Force + } + + $result.Files += (Get-Item $filePath).FullName + } + + return $result + } + + function GenerateTestAssembly + { + $assemblyPath = Join-Path $env:TEMP TestModule + $outputPath = Join-Path $assemblyPath TestModule.dll + + if (-not (Test-Path $assemblyPath)) + { + New-Item $assemblyPath -Force -ItemType Directory | Out-Null + } + + if (-not (Test-Path $outputPath)) + { + $code = @" + namespace TestModule + { + using System; + using System.Management.Automation; + + [Cmdlet(VerbsCommon.Get, "TestModule")] + public class TestSameCmdlets : PSCmdlet + { + protected override void ProcessRecord() + { + WriteObject("TestModule"); + } + } + } +"@ + Add-Type -TypeDefinition $code -OutputAssembly $outputPath + } + + $result = @{ + ModuleName = "TestModule" + Path = (Get-Item $outputPath).FullName + } + + return $result + } + + function GetDestinationFolderPath + { + return (Get-Item $destinationDirectory).FullName + } + } + + AfterAll { + Remove-PSSession -Name $s.Name -ea SilentlyContinue + } + + BeforeEach { + <# Ensure we start with an empty test directory. Here is the file structure + + $destinationFolderName = "DestinationDirectory" + $sourceFolderName = "SourceDirectory" + $testDirectory = Join-Path "TestDrive:" "copyItemRemotely" + $destinationDirectory = Join-Path $testDirectory $destinationFolderName + $sourceDirectory = Join-Path $testDirectory $sourceFolderName + #> + + if (test-path $testDirectory) + { + Remove-Item $testDirectory -Force -ea SilentlyContinue -Recurse + } + + # Create testDirectory, and destinationDirectory + New-Item $testDirectory -ItemType Directory -Force | Out-Null + New-Item $destinationDirectory -ItemType Directory -Force | Out-Null + } + + Context "Validate Copy-Item Locally." { + It "Copy-Item -Path $filePath -Destination $destinationFolderPath" { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $filePath -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy-Item -Path $($testObject.SourceDirectory) -Destination $destinationFolderPath -Recurse" { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $testObject.SourceDirectory -Destination $destinationFolderPath -Recurse + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") + $copiedFilePath | should Exist + } + } + } + + Context "Validate Copy-Item to remote session." { + + It "Copy one file to remote session." { + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy one read only file to remote session." { + + $filePath = CreateTestFile -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -Force + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy-Item works for a read only file when '-Force' is not used." { + + $filePath = CreateTestFile -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -Verbose + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy one folder to session Recursively" { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $testObject.SourceDirectory -ToSession $s -Destination $destinationFolderPath -Recurse + + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length + } + } + + It "Copy folder with read only files to remote session recursively." { + $testObject = CreateTestDirectory -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $testObject.SourceDirectory -ToSession $s -Destination $destinationFolderPath -Recurse -Force + + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length + } + } + + It "Copy one file to remote session fails when the remote directory does not exist." { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + $destinationFolderPath = Join-Path $destinationFolderPath "A\B\C\D\E" + $expectedFullyQualifiedErrorId = 'RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand' + + try + { + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -ErrorAction Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId + } + } + + It "Copy folder to remote session recursively works even if the target directory does not exist." { + $testObject = CreateTestDirectory -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + $destinationFolderPath = Join-Path $destinationFolderPath "FoderThatDoesNotExist" + Copy-Item -Path $testObject.SourceDirectory -ToSession $s -Destination $destinationFolderPath -Recurse -Force + + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\FoderThatDoesNotExist") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length + } + } + + It "Copy one empty file to remote session." { + + $filePath = CreateTestFile -emptyFile + $destinationFolderPath = GetDestinationFolderPath + $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") + $copiedFilePath | should Not Exist + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $filePath).Length + } + + It "Copy-Item to session supports alternate data streams." { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + $streamContent = "This content is hidden" + $streamName = "Hidden" + Set-Content -Path $filePath -Value $streamContent -Stream $streamName + Copy-Item -Path $filePath -ToSession $s -Destination $destinationFolderPath -Verbose + ValidateCopyItemOperationForAlternateDataStream -filePath $filePath -streamName $streamName -expectedStreamContent $streamContent + } + } + + Context "Validate Copy-Item from remote session." { + + It "Copy one file from remote session." { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") + $copiedFilePath | should Not Exist + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy one empty file from remote session." { + + $filePath = CreateTestFile -emptyFile + $destinationFolderPath = GetDestinationFolderPath + $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") + $copiedFilePath | should Not Exist + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy folder from remote session recursively." { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + $files = @(Get-ChildItem $destinationFolderPath -Recurse -Force) + Copy-Item -Path $testObject.SourceDirectory -FromSession $s -Destination $destinationFolderPath -Recurse + + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\SourceDirectory") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length + } + } + + It "Copy one file from remote session fails when the target directory does not exist." { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + $destinationFolderPath = Join-Path $destinationFolderPath "A\B\C\D\E" + $expectedFullyQualifiedErrorId = 'CopyItemRemotelyIOError,Microsoft.PowerShell.Commands.CopyItemCommand' + try + { + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath -ErrorAction Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId + } + } + + It "Copy folder from remote session recursively works even if the target directory does not exist." { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + $destinationFolderPath = Join-Path $destinationFolderPath "FoderThatDoesNotExist" + $files = @(Get-ChildItem $destinationFolderPath -Recurse -Force) + Copy-Item -Path $testObject.SourceDirectory -FromSession $s -Destination $destinationFolderPath -Recurse + + foreach ($file in $testObject.Files) + { + $copiedFilePath = ([string]$file).Replace("SourceDirectory", "DestinationDirectory\FoderThatDoesNotExist") + $copiedFilePath | should Exist + (Get-Item $copiedFilePath).Length | should be (Get-Item $file).Length + } + } + + It "Copy a read only file from a remote session." { + + $filePath = CreateTestFile -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + $copiedFilePath = ([string]$filePath).Replace("SourceDirectory", "DestinationDirectory") + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath -Force + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy-Item for a read only file works with no '-force' parameter." { + + $filePath = CreateTestFile -setReadOnlyAttribute + $destinationFolderPath = GetDestinationFolderPath + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $filePath + } + + It "Copy-Item -FromSession works even when trying to copy an assembly that is currently being used by another process." { + + $testAssembly = GenerateTestAssembly + $destinationFolderPath = GetDestinationFolderPath + Import-Module $testAssembly.Path -Force + try + { + Copy-Item -Path $testAssembly.Path -FromSession $s -Destination $destinationFolderPath + ValidateCopyItemOperation -filePath $testAssembly.Path + } + finally + { + Remove-Module $testAssembly.ModuleName -Force -ea SilentlyContinue + } + } + + It "Copy-Item from session supports alternate data streams." { + + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + $streamContent = "This content is hidden" + $streamName = "Hidden" + Set-Content -Path $filePath -Value $streamContent -Stream $streamName + Copy-Item -Path $filePath -FromSession $s -Destination $destinationFolderPath + ValidateCopyItemOperationForAlternateDataStream -filePath $filePath -streamName $streamName -expectedStreamContent $streamContent + } + } + + Context "Validate Copy-Item Remotely using wildcards" { + + It "Copy-Item from session using wildcards." { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + $sourcePathWithWildcards = "$($testObject.SourceDirectory)\A\*.txt" + Copy-Item -Path $sourcePathWithWildcards -FromSession $s -Destination $destinationFolderPath -Force + + $sourceFiles = @(Get-Item $sourcePathWithWildcards) + foreach ($file in $sourceFiles) + { + $copiedFilePath = Join-Path $destinationFolderPath (Split-Path $file -Leaf) + $copiedFilePath | Should Exist + (Get-Item $copiedFilePath).Length | Should Be (Get-Item $file).Length + } + } + + It "Copy-Item to session using wildcards." { + + $testObject = CreateTestDirectory + $destinationFolderPath = GetDestinationFolderPath + $sourcePathWithWildcards = "$($testObject.SourceDirectory)\A\*.txt" + Copy-Item -Path $sourcePathWithWildcards -ToSession $s -Destination $destinationFolderPath -Force + + $sourceFiles = @(Get-Item $sourcePathWithWildcards) + foreach ($file in $sourceFiles) + { + $copiedFilePath = Join-Path $destinationFolderPath (Split-Path $file -Leaf) + $copiedFilePath | Should Exist + (Get-Item $copiedFilePath).Length | Should Be (Get-Item $file).Length + } + } + } + + Context "Validate FullyQualifiedErrorIds for remote source and destination paths." { + + BeforeAll { + # Create test file. + $testFilePath = Join-Path "TestDrive:" "testfile.txt" + if (test-path $testFilePath) + { + Remove-Item $testFilePath -Force -ea SilentlyContinue + } + "File test content" | Out-File $testFilePath -Force + } + + function Test-CopyItemError + { + param ($path, $destination, $expectedFullyQualifiedErrorId, $fromSession = $false) + + if ($fromSession) + { + It "Copy-Item FromSession -Path '$path' throws $expectedFullyQualifiedErrorId" { + try + { + Copy-Item -Path $path -FromSession $s -Destination $destination -ErrorAction Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId + } + } + } + else + { + It "Copy-Item ToSession -Destination '$path' throws $expectedFullyQualifiedErrorId" { + try + { + Copy-Item -Path $path -ToSession $s -Destination $destination -ErrorAction Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId + } + } + } + } + + $invalidSourcePathtestCases = @( + @{ + Path = "HKLM:\SOFTWARE" + Destination = $env:SystemDrive + ExpectedFullyQualifiedErrorId = "NamedParameterNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + @{ + Path = ".\Source" + Destination = $env:SystemDrive + ExpectedFullyQualifiedErrorId = "RemotePathIsNotAbsolute,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + @{ + Path = $env:SystemDrive + "\X\Y\Z" + Destination = $env:SystemDrive + "\A\B\C" + ExpectedFullyQualifiedErrorId = "RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + @{ + Path = $null + Destination = $env:SystemDrive + ExpectedFullyQualifiedErrorId = "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + @{ + Path = '' + Destination = $env:SystemDrive + ExpectedFullyQualifiedErrorId = "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + @{ + Path = "$env:SystemDrive\nonexistdir\*" + Destination = "$env:SystemDrive\psTest" + ExpectedFullyQualifiedErrorId = "RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" + FromSession = $true + } + ) + + foreach ($testCase in $invalidSourcePathtestCases) { + Test-CopyItemError @testCase + } + + $invalidDestinationPathtestCases = @( + @{ + Path = $testFilePath + Destination = ".\Source" + ExpectedFullyQualifiedErrorId = "RemotePathIsNotAbsolute,Microsoft.PowerShell.Commands.CopyItemCommand" + } + @{ + Path = $testFilePath + Destination = $env:SystemDrive + "\X\A\B\C" + ExpectedFullyQualifiedErrorId = "RemotePathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" + } + @{ + Path = $testFilePath + Destination = $null + ExpectedFullyQualifiedErrorId = "CopyItemRemoteDestinationIsNullOrEmpty,Microsoft.PowerShell.Commands.CopyItemCommand" + } + @{ + Path = $testFilePath + Destination = "" + ExpectedFullyQualifiedErrorId = "CopyItemRemoteDestinationIsNullOrEmpty,Microsoft.PowerShell.Commands.CopyItemCommand" + } + @{ + Path = "$env:SystemDrive\nonexistdir\*" + Destination = "$env:SystemDrive\psTest" + ExpectedFullyQualifiedErrorId = "PathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand" + } + ) + + foreach ($testCase in $invalidDestinationPathtestCases) { + Test-CopyItemError @testCase + } + } +} + +Describe "Validate Copy-Item error for target sessions not in FullLanguageMode." -Tags "Feature" { + + BeforeAll { + + $testDirectory = "TestDrive:\" + + # Create the test file and directories. + $source = "$testDirectory\Source" + $destination = "$testDirectory\Destination" + + New-Item $source -ItemType Directory -Force | Out-Null + New-Item $destination -ItemType Directory -Force | Out-Null + + $testFilePath = Join-Path $source "testfile.txt" + "File test content" | Out-File $testFilePath -Force + + # Keep track of the sessions. + $testSessions = @{} + + # Keep track of the session names to be unregistered. + $sessionToUnregister = @() + + $languageModes = @("ConstrainedLanguage", "NoLanguage", "RestrictedLanguage") + $id = (Get-Random).ToString() + + foreach ($languageMode in $languageModes) + { + $sessionName = $languageMode + "_" + $id + $sessionToUnregister += $sessionName + $configFilePath = Join-Path $testDirectory "test.pssc" + + # Create the session. + Write-Host "Creating pssession with '$languageMode' ..." + New-PSSessionConfigurationFile -Path $configFilePath -SessionType Default -LanguageMode $languageMode + Register-PSSessionConfiguration -Name $sessionName -Path $configFilePath -Force | Out-Null + $testSession = New-PSSession -ConfigurationName $sessionName + + # Validate that the session is opened. + $testSession.State | Should Be "Opened" + + # Add the new session to the list. + $testSessions[$languageMode] = $testSession + + # Remove the pssc file. + Remove-Item $configFilePath -Force -ea SilentlyContinue + } + } + + AfterAll { + + $testSessions.Values | Remove-PSSession -ea SilentlyContinue + + $sessionToUnregister | foreach { + Unregister-PSSessionConfiguration -Name $_ -Force -ea SilentlyContinue + } + } + + foreach ($languageMode in $testSessions.Keys) + { + $session = $testSessions[$languageMode] + + It "Copy-Item throws 'SessionIsNotInFullLanguageMode' error for a session in '$languageMode'" { + + # FromSession + try + { + Copy-Item -Path $testFilePath -FromSession $session -Destination $destination -Force -Verbose -ea Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be "SessionIsNotInFullLanguageMode,Microsoft.PowerShell.Commands.CopyItemCommand" + } + + # ToSession + try + { + Copy-Item -Path $testFilePath -ToSession $session -Destination $destination -Force -Verbose -ea Stop + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be "SessionIsNotInFullLanguageMode,Microsoft.PowerShell.Commands.CopyItemCommand" + } + } + } +} + +Describe "Copy-Item can use Recurse and Exclude together" -Tags "Feature" { + + Context "Local and Remote Tests" { + + BeforeAll { + $s = New-PSSession -ComputerName . -ea SilentlyContinue + if (-not $s) + { + throw "Failed to create PSSession for remote copy operations." + } + + $null = New-Item -ItemType Directory -Path "TestDrive:\Parent\Sub" + $null = New-Item -Path "TestDrive:\Parent\p1.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\p2.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\s4.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\Sub\s1.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\Sub\s2.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\Sub\s3.txt" -Value "test" + $null = New-Item -Path "TestDrive:\Parent\Sub\p3.txt" -Value "testcl" + } + + It "can exclude files at sub directory" { + Copy-Item -Path TestDrive:\Parent\* -Recurse -Exclude s*.txt -Destination TestDrive:\Temp -Force + $copiedFiles = Get-ChildItem -Recurse -Path TestDrive:\Temp + $copiedFiles.Count | Should Be 3 + } + + It "can exclude files at sub directory to a session" { + Copy-Item -Path TestDrive:\Parent\* -Recurse -Exclude s*.txt -Destination $TestDrive\Temp2 -Force -ToSession $s + $copiedFiles = Get-ChildItem -Recurse -Path TestDrive:\Temp + $copiedFiles.Count | Should Be 3 + } + + It "can exclude files at sub directory from a session" { + Copy-Item -Path $TestDrive\Parent\* -Recurse -Exclude s*.txt -Destination TestDrive:\Temp3 -FromSession $s + $copiedFiles = Get-ChildItem -Recurse -Path TestDrive:\Temp2 + $copiedFiles.Count | Should Be 3 + } + + AfterAll { + Remove-PSSession -Session $s -ErrorAction SilentlyContinue + } + } +} + +Describe "Copy-Item remotely bug fixes" -Tags "Feature" { + + BeforeAll { + $s = New-PSSession -ComputerName . -ErrorAction SilentlyContinue + if (-not $s) + { + throw "Failed to create PSSession for remote copy operations." + } + + $originalContent = "test file 1 - Source" + $newContent = "This is some new content" + + $null = New-Item -ItemType Directory -Path "TestDrive:\Source" + $null = New-Item -ItemType Directory -Path "TestDrive:\Destination" + } + + AfterAll { + Remove-PSSession -Session $s -ErrorAction SilentlyContinue + } + + BeforeEach { + + # Create the same file in the source and destination + Set-Content -Path "TestDrive:\Source\testFile1.txt" -Value $originalContent -Force + Set-Content -Path "TestDrive:\Destination\testFile1.txt" -Value $originalContent -Force + } + + Context "Copy-Item remotely overwrites a destination file if it exists." { + + BeforeEach { + + # Overwrite the source file + Set-Content -Path "TestDrive:\Source\testFile1.txt" -Value $newContent + } + + It "Copy item -tosession overwrites the content of an existing file." { + + # Copy file to session + Copy-Item -Path "TestDrive:\Source\testFile1.txt" -Destination "$TestDrive\Destination\testFile1.txt" -ToSession $s + + # Validate the the file was overwritten + $fileContent = Get-Content "TestDrive:\Destination\testFile1.txt" -ea SilentlyContinue -Raw + $fileContent | Should Match $newContent + } + + It "Copy item -fromsession overwrites the content of an existing file." { + + # Copy file to session + Copy-Item -Path "$TestDrive\Source\testFile1.txt" -Destination "TestDrive:\Destination\testFile1.txt" -FromSession $s + + # Validate the the file was overwritten + $fileContent = Get-Content "TestDrive:\Destination\testFile1.txt" -ea SilentlyContinue -Raw + $fileContent | Should Match $newContent + } + } + + Context "Copy-Item remotely creates a destination file if it does not exist." { + + BeforeEach { + + if (Test-Path "TestDrive:\AnotherDestination") + { + Remove-Item "TestDrive:\AnotherDestination" -Force -Recurse -ea SilentlyContinue + } + $null = New-Item -ItemType Directory -Path "TestDrive:\AnotherDestination" + + # Ensure the file does not exist + "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" | Should Not Exist + } + + It "Copy-Item -tosession creates the file if it does not exist on the remote destination." { + + # Copy file to session + Copy-Item -Path "TestDrive:\Source\testFile1.txt" -Destination "$TestDrive\AnotherDestination\FileThatDoesNotExist.txt" -ToSession $s + + # Verify that the file was created + "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" | Should Exist + } + + It "Copy-Item -fromsession creates the file if it does not exist on the local machine." { + + # Copy file from session + Copy-Item -Path "$TestDrive\Source\testFile1.txt" -Destination "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" -FromSession $s + + # Verify that the file was created + "TestDrive:\AnotherDestination\FileThatDoesNotExist.txt" | Should Exist + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1 index 24941dc33..1be6c38dd 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1 @@ -1,26 +1,26 @@ -# Tests related to TFS item 1370133 [PSUpgrade] Need -NoNewline parameter on Out-File, Add-Content and Set-Content -# Connect request https://connect.microsoft.com/PowerShell/feedback/details/524739/need-nonewline-parameter-on-out-file-add-content-and-set-content - -Describe "Tests for -NoNewline parameter of Out-File, Add-Content and Set-Content" -tags "Feature" { - - It "NoNewline parameter works on Out-File" { - $temp = New-TemporaryFile - 1..5 | Out-File $temp.FullName -Encoding 'ASCII' -NoNewline - (Get-Content $temp -Encoding Byte).Count | Should Be 5 - Remove-Item $temp -ErrorAction SilentlyContinue -Force - } - - It "NoNewline parameter works on Set-Content" { - $temp = New-TemporaryFile - Set-Content -Path $temp.FullName -Value 'a','b','c' -Encoding 'ASCII' -NoNewline - (Get-Content $temp -Encoding Byte).Count | Should Be 3 - Remove-Item $temp -ErrorAction SilentlyContinue -Force - } - - It "NoNewline parameter works on Add-Content" { - $temp = New-TemporaryFile - 1..9 | %{Add-Content -Path $temp.FullName -Value $_ -Encoding 'ASCII' -NoNewline} - (Get-Content $temp -Encoding Byte).Count | Should Be 9 - Remove-Item $temp -ErrorAction SilentlyContinue -Force - } -} +# Tests related to TFS item 1370133 [PSUpgrade] Need -NoNewline parameter on Out-File, Add-Content and Set-Content +# Connect request https://connect.microsoft.com/PowerShell/feedback/details/524739/need-nonewline-parameter-on-out-file-add-content-and-set-content + +Describe "Tests for -NoNewline parameter of Out-File, Add-Content and Set-Content" -tags "Feature" { + + It "NoNewline parameter works on Out-File" { + $temp = New-TemporaryFile + 1..5 | Out-File $temp.FullName -Encoding 'ASCII' -NoNewline + (Get-Content $temp -Encoding Byte).Count | Should Be 5 + Remove-Item $temp -ErrorAction SilentlyContinue -Force + } + + It "NoNewline parameter works on Set-Content" { + $temp = New-TemporaryFile + Set-Content -Path $temp.FullName -Value 'a','b','c' -Encoding 'ASCII' -NoNewline + (Get-Content $temp -Encoding Byte).Count | Should Be 3 + Remove-Item $temp -ErrorAction SilentlyContinue -Force + } + + It "NoNewline parameter works on Add-Content" { + $temp = New-TemporaryFile + 1..9 | %{Add-Content -Path $temp.FullName -Value $_ -Encoding 'ASCII' -NoNewline} + (Get-Content $temp -Encoding Byte).Count | Should Be 9 + Remove-Item $temp -ErrorAction SilentlyContinue -Force + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 index b91c7aebd..b5437fc7e 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 @@ -1,221 +1,221 @@ -# This is a Pester test suite to validate the Format-Hex cmdlet in the Microsoft.PowerShell.Utility module. -# -# Copyright (c) Microsoft Corporation, 2015 -# - -<# - Purpose: - Verify that Format-Hex display the Hexa decmial value for the input data. - - Action: - Run Format-Fex. - - Expected Result: - Hexa decimal equivalent of the input data is displayed. -#> - -Describe "FormatHex" -tags "CI" { - BeforeAll { - Setup -d FormatHexDataDir - $inputText1 = 'Hello World' - $inputText2 = 'This is a bit more text' - $inputFile1 = setup -f "FormatHexDataDir/SourceFile-1.txt" -content $inputText1 -pass - $inputFile2 = setup -f "FormatHexDataDir/SourceFile-2.txt" -content $inputText2 -pass - } - - # This test is to validate to pipeline support in Format-Hex cmdlet. - It "ValidatePipelineSupport" { - - # InputObject Parameter set should get invoked and - # the input data should be treated as string. - $result = $inputText1 | Format-Hex - $result | Should Not Be $null - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - ($actualResult -match $inputText1) | Should Be $true - } - - # This test is to validate to pipeline support in Format-Hex cmdlet. - It "ValidateByteArrayInputSupport" { - - # InputObject Parameter set should get invoked and - # the input data should be treated as byte[]. - $inputBytes = [System.Text.Encoding]::ASCII.GetBytes($inputText1) - - $result = Format-Hex -InputObject $inputBytes - $result | Should Not Be $null - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - ($actualResult -match $inputText1) | Should Be $true - } - - # This test is to validate to input given through Path paramter set in Format-Hex cmdlet. - It "ValidatePathParameterSet" { - - $result = Format-Hex -Path $inputFile1 - $result | Should Not Be $null - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - ($actualResult -match $inputText1) | Should Be $true - } - - # This test is to validate to Path paramter set is considered as default in Format-Hex cmdlet. - It "ValidatePathAsDefaultParameterSet" { - - $result = Format-Hex $inputFile1 - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - ($actualResult -match $inputText1) | Should Be $true - } - - # This test is to validate to input given through LiteralPath paramter set in Format-Hex cmdlet. - It "ValidateLiteralPathParameterSet" { - - $result = Format-Hex -LiteralPath $inputFile1 - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - ($actualResult -match $inputText1) | Should Be $true - } - - # This test is to validate to input given through pipeline. The input being piped from results of Get-hildItem - It "ValidateFileInfoPipelineInput" { - - $result = Get-ChildItem $inputFile1 | Format-Hex - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - ($actualResult -match $inputText1) | Should Be $true - } - - # This test is to validate Encoding formats functionality of Format-Hex cmdlet. - It "ValidateEncodingFormats" { - - $result = Format-Hex -InputObject $inputText1 -Encoding ASCII - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - ($actualResult -match $inputText1) | Should Be $true - } - - # This test is to validate that integers can be piped to the format-hex - It "ValidateIntegerInput" { - - $result = 1,2,3,4 | Format-Hex - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - # whitespace sensitive - $actualResult | should be "00000000 01 02 03 04 .... " - } - - # This test is to validate that integers can be piped to the format-hex - # and properly represented as characters in the string - It "ValidateIntegerInputThatPresentAsCharacters" { - - $result = 65..68 | Format-Hex - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - # whitespace sensitive - $actualResult | should be "00000000 41 42 43 44 ABCD " - } - - # This test is to validate that integers can be piped to the format-hex - It "ValidateIntegerRawInput" { - - $result = 1,2,3,4 | Format-Hex -Raw - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - # whitespace sensitive - $actualResult | should be "00000000 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 ................" - } - - # handle int64 - It "ValidateInteger64" { - - $result = [int64]::MaxValue | Format-Hex - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() - # whitespace sensitive - $actualResult | Should Match "00000000 FF FF FF FF FF FF FF 7F ." - } - - # handle bytes, int16, int32, and int64 - It "Validate combined and reduced number formatting" { - $b = 65 # fits in a byte - $i16 = 32767 # fits in an int16 - $i32 = 2147483647 # an int32 - $i64 = 9223372036854775807 # an int64 - $result = $b,$i16,$i32,$i64 | format-Hex - $result.GetType().Name | should be 'ByteCollection' - $actualResult = $result.ToString() - $actualResult | should Match "00000000 41 FF 7F FF FF FF 7F FF FF FF FF FF FF FF 7F A" - } - - # handle bytes, int16, int32, and int64 - It "Validate combined and with raw number formatting" { - $b = 65 # fits in a byte - $i16 = 32767 # fits in an int16 - $i32 = 2147483647 # an int32 - $i64 = 9223372036854775807 # an int64 - # this will cause 2 lines to be emitted - $result = $b,$i16,$i32,$i64 | format-Hex -Raw - $result[0].GetType().Name | should be 'ByteCollection' - $result[1].GetType().Name | should be 'ByteCollection' - $result0 = $result[0].ToString() - $result0 | should match "00000000 41 00 00 00 FF 7F 00 00 FF FF FF 7F FF FF FF FF A" - $result1 = $result[1].ToString() - $result1 | should match "00000010 FF FF FF 7F .." - } - - # This test is to validate that streamed text does not have buffer underrun problems - It "ValidateEachBufferHasCorrectContentForStreamingText" { - $result = "a" * 30 | Format-Hex - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be 'ByteCollection' - $actualResult = $result.ToString() -split "`r`n" - $actualResult.Count | should be 2 - $actualResult[0].ToString() | Should be "00000000 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaaaa" - $actualResult[1].ToString() | Should be "00000010 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaa " - } - - # This test is to validate that files do not have buffer underrun problems - It "ValidateEachBufferHasCorrectContentForFiles" { - $result = Format-Hex -path $InputFile2 - $result | Should Not BeNullOrEmpty - $result.Count | should be 2 - $result[0].ToString() | Should be "00000000 54 68 69 73 20 69 73 20 61 20 62 69 74 20 6D 6F This is a bit mo" - if ( $IsCore ) { - $result[1].ToString() | Should be "00000010 72 65 20 74 65 78 74 re text " - } - } - - # This test ensures that if we stream bytes from a file, the output is correct - It "ValidateStreamOfBytesFromFileHasProperOutput" { - $result = Get-Content $InputFile1 -Encoding Byte | Format-Hex - $result | Should Not BeNullOrEmpty - $result.GetType().Name | Should Be "ByteCollection" - if ( $IsCore ) { - $result.ToString() | Should be "00000000 48 65 6C 6C 6F 20 57 6F 72 6C 64 Hello World " - } - } - - # This test is to validate the alias for Format-Hex cmdlet. - It "ValidateCmdletAlias" { - - try - { - $result = Get-Command fhx -ErrorAction Stop - $result | Should Not BeNullOrEmpty - $result.CommandType.ToString() | Should Be "Alias" - } - catch - { - $_ | Should BeNullOrEmpty - } - } -} +# This is a Pester test suite to validate the Format-Hex cmdlet in the Microsoft.PowerShell.Utility module. +# +# Copyright (c) Microsoft Corporation, 2015 +# + +<# + Purpose: + Verify that Format-Hex display the Hexa decmial value for the input data. + + Action: + Run Format-Fex. + + Expected Result: + Hexa decimal equivalent of the input data is displayed. +#> + +Describe "FormatHex" -tags "CI" { + BeforeAll { + Setup -d FormatHexDataDir + $inputText1 = 'Hello World' + $inputText2 = 'This is a bit more text' + $inputFile1 = setup -f "FormatHexDataDir/SourceFile-1.txt" -content $inputText1 -pass + $inputFile2 = setup -f "FormatHexDataDir/SourceFile-2.txt" -content $inputText2 -pass + } + + # This test is to validate to pipeline support in Format-Hex cmdlet. + It "ValidatePipelineSupport" { + + # InputObject Parameter set should get invoked and + # the input data should be treated as string. + $result = $inputText1 | Format-Hex + $result | Should Not Be $null + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText1) | Should Be $true + } + + # This test is to validate to pipeline support in Format-Hex cmdlet. + It "ValidateByteArrayInputSupport" { + + # InputObject Parameter set should get invoked and + # the input data should be treated as byte[]. + $inputBytes = [System.Text.Encoding]::ASCII.GetBytes($inputText1) + + $result = Format-Hex -InputObject $inputBytes + $result | Should Not Be $null + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText1) | Should Be $true + } + + # This test is to validate to input given through Path paramter set in Format-Hex cmdlet. + It "ValidatePathParameterSet" { + + $result = Format-Hex -Path $inputFile1 + $result | Should Not Be $null + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText1) | Should Be $true + } + + # This test is to validate to Path paramter set is considered as default in Format-Hex cmdlet. + It "ValidatePathAsDefaultParameterSet" { + + $result = Format-Hex $inputFile1 + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText1) | Should Be $true + } + + # This test is to validate to input given through LiteralPath paramter set in Format-Hex cmdlet. + It "ValidateLiteralPathParameterSet" { + + $result = Format-Hex -LiteralPath $inputFile1 + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText1) | Should Be $true + } + + # This test is to validate to input given through pipeline. The input being piped from results of Get-hildItem + It "ValidateFileInfoPipelineInput" { + + $result = Get-ChildItem $inputFile1 | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText1) | Should Be $true + } + + # This test is to validate Encoding formats functionality of Format-Hex cmdlet. + It "ValidateEncodingFormats" { + + $result = Format-Hex -InputObject $inputText1 -Encoding ASCII + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + ($actualResult -match $inputText1) | Should Be $true + } + + # This test is to validate that integers can be piped to the format-hex + It "ValidateIntegerInput" { + + $result = 1,2,3,4 | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + # whitespace sensitive + $actualResult | should be "00000000 01 02 03 04 .... " + } + + # This test is to validate that integers can be piped to the format-hex + # and properly represented as characters in the string + It "ValidateIntegerInputThatPresentAsCharacters" { + + $result = 65..68 | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + # whitespace sensitive + $actualResult | should be "00000000 41 42 43 44 ABCD " + } + + # This test is to validate that integers can be piped to the format-hex + It "ValidateIntegerRawInput" { + + $result = 1,2,3,4 | Format-Hex -Raw + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + # whitespace sensitive + $actualResult | should be "00000000 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 ................" + } + + # handle int64 + It "ValidateInteger64" { + + $result = [int64]::MaxValue | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() + # whitespace sensitive + $actualResult | Should Match "00000000 FF FF FF FF FF FF FF 7F ." + } + + # handle bytes, int16, int32, and int64 + It "Validate combined and reduced number formatting" { + $b = 65 # fits in a byte + $i16 = 32767 # fits in an int16 + $i32 = 2147483647 # an int32 + $i64 = 9223372036854775807 # an int64 + $result = $b,$i16,$i32,$i64 | format-Hex + $result.GetType().Name | should be 'ByteCollection' + $actualResult = $result.ToString() + $actualResult | should Match "00000000 41 FF 7F FF FF FF 7F FF FF FF FF FF FF FF 7F A" + } + + # handle bytes, int16, int32, and int64 + It "Validate combined and with raw number formatting" { + $b = 65 # fits in a byte + $i16 = 32767 # fits in an int16 + $i32 = 2147483647 # an int32 + $i64 = 9223372036854775807 # an int64 + # this will cause 2 lines to be emitted + $result = $b,$i16,$i32,$i64 | format-Hex -Raw + $result[0].GetType().Name | should be 'ByteCollection' + $result[1].GetType().Name | should be 'ByteCollection' + $result0 = $result[0].ToString() + $result0 | should match "00000000 41 00 00 00 FF 7F 00 00 FF FF FF 7F FF FF FF FF A" + $result1 = $result[1].ToString() + $result1 | should match "00000010 FF FF FF 7F .." + } + + # This test is to validate that streamed text does not have buffer underrun problems + It "ValidateEachBufferHasCorrectContentForStreamingText" { + $result = "a" * 30 | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be 'ByteCollection' + $actualResult = $result.ToString() -split "`r`n" + $actualResult.Count | should be 2 + $actualResult[0].ToString() | Should be "00000000 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaaaa" + $actualResult[1].ToString() | Should be "00000010 61 61 61 61 61 61 61 61 61 61 61 61 61 61 aaaaaaaaaaaaaa " + } + + # This test is to validate that files do not have buffer underrun problems + It "ValidateEachBufferHasCorrectContentForFiles" { + $result = Format-Hex -path $InputFile2 + $result | Should Not BeNullOrEmpty + $result.Count | should be 2 + $result[0].ToString() | Should be "00000000 54 68 69 73 20 69 73 20 61 20 62 69 74 20 6D 6F This is a bit mo" + if ( $IsCore ) { + $result[1].ToString() | Should be "00000010 72 65 20 74 65 78 74 re text " + } + } + + # This test ensures that if we stream bytes from a file, the output is correct + It "ValidateStreamOfBytesFromFileHasProperOutput" { + $result = Get-Content $InputFile1 -Encoding Byte | Format-Hex + $result | Should Not BeNullOrEmpty + $result.GetType().Name | Should Be "ByteCollection" + if ( $IsCore ) { + $result.ToString() | Should be "00000000 48 65 6C 6C 6F 20 57 6F 72 6C 64 Hello World " + } + } + + # This test is to validate the alias for Format-Hex cmdlet. + It "ValidateCmdletAlias" { + + try + { + $result = Get-Command fhx -ErrorAction Stop + $result | Should Not BeNullOrEmpty + $result.CommandType.ToString() | Should Be "Alias" + } + catch + { + $_ | Should BeNullOrEmpty + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 index 73aa5a9b8..04bc41d89 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 @@ -1,84 +1,84 @@ -Describe "Using delimiters with Export-CSV and Import-CSV behave correctly" -tags "Feature" { - BeforeAll { - # note, we will not use "," as that's the default for CSV - $delimiters = "/", " ", "@", "#", "$", "\", "&", "(", ")", - "{", "}", "|", "<", ">", ";", "'", - '"', "~", "!", "%", "^", "*", "_", "+", ":", - "?", "-", "=", "[", "]", "." - $defaultDelimiter = [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator - # With CORECLR the CurrentCulture.TextInfo.ListSeparator is not writable, so - # we need to use an entirely new CultureInfo which we can modify - $enCulture = [System.Globalization.CultureInfo]::new("en-us") - $d = get-date - $testCases = @( - foreach($del in $delimiters) - { - @{ Delimiter = $del; Data = $d; ExpectedResult = $d.Ticks } - } - ) - function Set-delimiter { - param ( $delimiter ) - if ( $IsCore ) { - $enCulture.TextInfo.ListSeparator = $delimiter - [System.Globalization.CultureInfo]::CurrentCulture = $enCulture - } - else { - [System.Globalization.cultureInfo]::CurrentCulture.TextInfo.ListSeparator = $delimiter - } - } - } - AfterEach { - if ( $IsCore ) { - $enCulture.TextInfo.ListSeparator = $defaultDelimiter - [System.Globalization.CultureInfo]::CurrentCulture = $enCulture - } - else { - [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator = $defaultDelimiter - } - remove-item -force -ea silentlycontinue TESTDRIVE:/file.csv - } - - It "Disallow use of null delimiter" { - $d | export-csv TESTDRIVE:/file.csv - { import-csv -path TESTDRIVE:/file.csv -delimiter $null } | Should Throw "Delimiter" - } - - It "Disallow use of delimiter with useCulture parameter" { - $d | export-csv TESTDRIVE:/file.csv - { import-csv -path TESTDRIVE:/file.csv -useCulture "," } | Should Throw "','" - } - - It "Imports the same properties as exported" { - $a = [pscustomobject]@{ a = 1; b = 2; c = 3 } - $a | export-Csv TESTDRIVE:/file.csv - $b = import-csv TESTDRIVE:/file.csv - @($b.psobject.properties).count | should be 3 - $b.a | Should be $a.a - $b.b | Should be $a.b - $b.c | Should be $a.c - } - - # parameter generated tests - It 'Delimiter with CSV import will fail correctly when culture does not match' -testCases $testCases { - param ($delimiter, $Data, $ExpectedResult) - set-Delimiter $delimiter - $Data | export-CSV TESTDRIVE:\File.csv -useCulture - $i = Import-CSV TESTDRIVE:\File.csv - $i.Ticks | Should Not Be $ExpectedResult - } - - It 'Delimiter with CSV import will succeed when culture matches export' -testCases $testCases { - param ($delimiter, $Data, $ExpectedResult) - set-Delimiter $delimiter - $Data | export-CSV TESTDRIVE:\File.csv -useCulture - $i = Import-CSV TESTDRIVE:\File.csv -useCulture - $i.Ticks | Should Be $ExpectedResult - } - - It 'Delimiter with CSV import will succeed when delimiter is used explicitly' -testCases $testCases { - param ($delimiter, $Data, $ExpectedResult) - $Data | export-CSV TESTDRIVE:\File.csv -delimiter $delimiter - $i = Import-CSV TESTDRIVE:\File.csv -delimiter $delimiter - $i.Ticks | Should Be $ExpectedResult - } -} +Describe "Using delimiters with Export-CSV and Import-CSV behave correctly" -tags "Feature" { + BeforeAll { + # note, we will not use "," as that's the default for CSV + $delimiters = "/", " ", "@", "#", "$", "\", "&", "(", ")", + "{", "}", "|", "<", ">", ";", "'", + '"', "~", "!", "%", "^", "*", "_", "+", ":", + "?", "-", "=", "[", "]", "." + $defaultDelimiter = [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator + # With CORECLR the CurrentCulture.TextInfo.ListSeparator is not writable, so + # we need to use an entirely new CultureInfo which we can modify + $enCulture = [System.Globalization.CultureInfo]::new("en-us") + $d = get-date + $testCases = @( + foreach($del in $delimiters) + { + @{ Delimiter = $del; Data = $d; ExpectedResult = $d.Ticks } + } + ) + function Set-delimiter { + param ( $delimiter ) + if ( $IsCore ) { + $enCulture.TextInfo.ListSeparator = $delimiter + [System.Globalization.CultureInfo]::CurrentCulture = $enCulture + } + else { + [System.Globalization.cultureInfo]::CurrentCulture.TextInfo.ListSeparator = $delimiter + } + } + } + AfterEach { + if ( $IsCore ) { + $enCulture.TextInfo.ListSeparator = $defaultDelimiter + [System.Globalization.CultureInfo]::CurrentCulture = $enCulture + } + else { + [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ListSeparator = $defaultDelimiter + } + remove-item -force -ea silentlycontinue TESTDRIVE:/file.csv + } + + It "Disallow use of null delimiter" { + $d | export-csv TESTDRIVE:/file.csv + { import-csv -path TESTDRIVE:/file.csv -delimiter $null } | Should Throw "Delimiter" + } + + It "Disallow use of delimiter with useCulture parameter" { + $d | export-csv TESTDRIVE:/file.csv + { import-csv -path TESTDRIVE:/file.csv -useCulture "," } | Should Throw "','" + } + + It "Imports the same properties as exported" { + $a = [pscustomobject]@{ a = 1; b = 2; c = 3 } + $a | export-Csv TESTDRIVE:/file.csv + $b = import-csv TESTDRIVE:/file.csv + @($b.psobject.properties).count | should be 3 + $b.a | Should be $a.a + $b.b | Should be $a.b + $b.c | Should be $a.c + } + + # parameter generated tests + It 'Delimiter with CSV import will fail correctly when culture does not match' -testCases $testCases { + param ($delimiter, $Data, $ExpectedResult) + set-Delimiter $delimiter + $Data | export-CSV TESTDRIVE:\File.csv -useCulture + $i = Import-CSV TESTDRIVE:\File.csv + $i.Ticks | Should Not Be $ExpectedResult + } + + It 'Delimiter with CSV import will succeed when culture matches export' -testCases $testCases { + param ($delimiter, $Data, $ExpectedResult) + set-Delimiter $delimiter + $Data | export-CSV TESTDRIVE:\File.csv -useCulture + $i = Import-CSV TESTDRIVE:\File.csv -useCulture + $i.Ticks | Should Be $ExpectedResult + } + + It 'Delimiter with CSV import will succeed when delimiter is used explicitly' -testCases $testCases { + param ($delimiter, $Data, $ExpectedResult) + $Data | export-CSV TESTDRIVE:\File.csv -delimiter $delimiter + $i = Import-CSV TESTDRIVE:\File.csv -delimiter $delimiter + $i.Ticks | Should Be $ExpectedResult + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1 index 831a1292a..c7a1f73f5 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/MiscCmdletUpdates.Tests.ps1 @@ -1,54 +1,54 @@ -Describe "GetDateFormatUpdates" -Tags "Feature" { - - It "Verifies that FileDate format works" { - $date = Get-Date - $expectedFormat = "{0:yyyyMMdd}" -f $date - $actualFormat = Get-Date -Date $date -Format FileDate - - $actualFormat | Should be $expectedFormat - } - - It "Verifies that FileDateUniversal format works" { - $date = (Get-Date).ToUniversalTime() - $expectedFormat = "{0:yyyyMMddZ}" -f $date - $actualFormat = Get-Date -Date $date -Format FileDateUniversal - - $actualFormat | Should be $expectedFormat - } - - It "Verifies that FileDateTime format works" { - $date = Get-Date - $expectedFormat = "{0:yyyyMMddTHHmmssffff}" -f $date - $actualFormat = Get-Date -Date $date -Format FileDateTime - - $actualFormat | Should be $expectedFormat - } - - It "Verifies that FileDateTimeUniversal format works" { - $date = (Get-Date).ToUniversalTime() - $expectedFormat = "{0:yyyyMMddTHHmmssffffZ}" -f $date - $actualFormat = Get-Date -Date $date -Format FileDateTimeUniversal - - $actualFormat | Should be $expectedFormat - } - -} - -Describe "GetRandomMiscTests" -Tags "Feature" { - It "Shouldn't overflow when using max range" { - - $hadError = $false - - try - { - ## Don't actually need to validate - Get-Random -Minimum ([Int32]::MinValue) -Maximum ([Int32]::MaxValue) -ErrorAction Stop - } - catch - { - $hadError = $true - } - - $hadError | Should be $false - } -} +Describe "GetDateFormatUpdates" -Tags "Feature" { + + It "Verifies that FileDate format works" { + $date = Get-Date + $expectedFormat = "{0:yyyyMMdd}" -f $date + $actualFormat = Get-Date -Date $date -Format FileDate + + $actualFormat | Should be $expectedFormat + } + + It "Verifies that FileDateUniversal format works" { + $date = (Get-Date).ToUniversalTime() + $expectedFormat = "{0:yyyyMMddZ}" -f $date + $actualFormat = Get-Date -Date $date -Format FileDateUniversal + + $actualFormat | Should be $expectedFormat + } + + It "Verifies that FileDateTime format works" { + $date = Get-Date + $expectedFormat = "{0:yyyyMMddTHHmmssffff}" -f $date + $actualFormat = Get-Date -Date $date -Format FileDateTime + + $actualFormat | Should be $expectedFormat + } + + It "Verifies that FileDateTimeUniversal format works" { + $date = (Get-Date).ToUniversalTime() + $expectedFormat = "{0:yyyyMMddTHHmmssffffZ}" -f $date + $actualFormat = Get-Date -Date $date -Format FileDateTimeUniversal + + $actualFormat | Should be $expectedFormat + } + +} + +Describe "GetRandomMiscTests" -Tags "Feature" { + It "Shouldn't overflow when using max range" { + + $hadError = $false + + try + { + ## Don't actually need to validate + Get-Random -Minimum ([Int32]::MinValue) -Maximum ([Int32]::MaxValue) -ErrorAction Stop + } + catch + { + $hadError = $true + } + + $hadError | Should be $false + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1 index 39757d61d..95fc37cf0 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/NewGuid.Tests.ps1 @@ -1,19 +1,19 @@ -Describe "New-Guid" -Tags "CI" { - - It "returns a new guid" { - $guid = New-Guid - $guid.GetType().FullName | Should Be "System.Guid" - } - - It "should not be all zeros" { - $guid = New-Guid - $guid.ToString() | Should Not Be "00000000-0000-0000-0000-000000000000" - } - - It "should return different guids with each call" { - $guid1 = New-Guid - $guid2 = New-Guid - $guid1.ToString() | Should Not Be $guid2.ToString() - } -} - +Describe "New-Guid" -Tags "CI" { + + It "returns a new guid" { + $guid = New-Guid + $guid.GetType().FullName | Should Be "System.Guid" + } + + It "should not be all zeros" { + $guid = New-Guid + $guid.ToString() | Should Not Be "00000000-0000-0000-0000-000000000000" + } + + It "should return different guids with each call" { + $guid1 = New-Guid + $guid2 = New-Guid + $guid1.ToString() | Should Not Be $guid2.ToString() + } +} + diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1 index 0c496b4a5..87bbefb3b 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/NewTemporaryFile.Tests.ps1 @@ -1,38 +1,38 @@ -# This is a Pester test suite to validate the New-TemporaryFile cmdlet in the Microsoft.PowerShell.Utility module. -# -# Copyright (c) Microsoft Corporation, 2015 -# - -<# - Purpose: - Verify that New-TemporaryFile creates a temporary file. - - Action: - Run New-TemporaryFile. - - Expected Result: - A FileInfo object for the temporary file is returned. -#> - -Describe "NewTemporaryFile" -Tags "CI" { - - It "creates a new temporary file" { - $tempFile = New-TemporaryFile - - Test-Path $tempFile | Should be $true - $tempFile.GetType().Name | Should be "FileInfo" - - if(Test-Path $tempFile) - { - Remove-Item $tempFile -ErrorAction SilentlyContinue -Force - } - } - - It "with WhatIf does not create a file" { - New-TemporaryFile -WhatIf | Should Be $null - } - - It "has an OutputType of System.IO.FileInfo" { - (Get-Command New-TemporaryFile).OutputType | Should Be "System.IO.FileInfo" - } -} +# This is a Pester test suite to validate the New-TemporaryFile cmdlet in the Microsoft.PowerShell.Utility module. +# +# Copyright (c) Microsoft Corporation, 2015 +# + +<# + Purpose: + Verify that New-TemporaryFile creates a temporary file. + + Action: + Run New-TemporaryFile. + + Expected Result: + A FileInfo object for the temporary file is returned. +#> + +Describe "NewTemporaryFile" -Tags "CI" { + + It "creates a new temporary file" { + $tempFile = New-TemporaryFile + + Test-Path $tempFile | Should be $true + $tempFile.GetType().Name | Should be "FileInfo" + + if(Test-Path $tempFile) + { + Remove-Item $tempFile -ErrorAction SilentlyContinue -Force + } + } + + It "with WhatIf does not create a file" { + New-TemporaryFile -WhatIf | Should Be $null + } + + It "has an OutputType of System.IO.FileInfo" { + (Get-Command New-TemporaryFile).OutputType | Should Be "System.IO.FileInfo" + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 index da48d6dd7..74c1c9312 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 @@ -1,1466 +1,1425 @@ -# -# Copyright (c) Microsoft Corporation, 2015 -# -# This is a Pester test suite which validate the Json cmdlets. -# - -# -# This 'Describe' is for tests that were converted from utscripts (SDXROOT/admin/monad/tests/monad/DRT/utscripts) -# and C# tests (SDXROOT/admin/monad/tests/monad/DRT/commands/utility/UnitTests) to Pester. -# -Describe "Json Tests" -Tags "Feature" { - - BeforeAll { - - function ValidateSampleObject - { - param ($result, [switch]$hasEmbeddedSampleObject ) - - Write-Verbose "validating deserialized SampleObject" -Verbose - $result.SampleInt | Should Be 98765 - $result.SampleString | Should Match "stringVal" - $result.SampleArray.Count | Should Be 2 - $result.SampleTrue | Should Be $true - $result.SampleFalse | Should Be $false - $result.SampleNull | Should Be $null - $result.SampleFloat | Should Be 9.8765E+43 - - if ($hasEmbeddedSampleObject) - { - Write-Verbose "validating deserialized Embedded SampleObject" -Verbose - ValidateSampleObject -result $result.SampleObject - } - } - - } - - Context "ConvertTo-Json Bug Fixes" { - - It "ConvertTo-JSON should not have hard coded english error message" { - - # Test follow-up for bug WinBlue: 163372 - ConvertTo-JSON has hard coded english error message. - $process = Get-Process -Id $PID - $hash = @{ $process = "def" } - $expectedFullyQualifiedErrorId = "NonStringKeyInDictionary,Microsoft.PowerShell.Commands.ConvertToJsonCommand" - - try - { - ConvertTo-Json -InputObject $hash - throw "CodeExecuted" - } - catch - { - $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId - } - } - - It "ConvertTo-Json should handle terms with double quotes" { - - # Test follow-up for bug WinBlue: 11484 - ConvertTo-Json can't handle terms with double quotes. - - $notcompressed = ConvertTo-JSON @{ FirstName = 'Hello " World' } - $compressed = ConvertTo-Json @{ FirstName = 'Hello " World' } -Compress - $valueFromNotCompressedResult = ConvertFrom-Json -InputObject $notcompressed - $valueFromCompressedResult = ConvertFrom-Json -InputObject $compressed - - $valueFromNotCompressedResult.FirstName | Should Match $valueFromCompressedResult.FirstName - } - - It "Convertto-Json should handle Enum based on Int64" { - - # Test follow-up for bug Win8: 378368 Convertto-Json problems with Enum based on Int64. - $src = @" -namespace Bug378368 -{ - public enum TestEnum : ulong - { - One = 1, - Two = 2 - } - - public enum TestEnum1 : long - { - One = 1, - Two = 2 - } - - public enum TestEnum2 : int - { - One = 1, - Two = 2 - } - - public class Test - { - public TestEnum TestEnum - { - get { return testEnum; } - set { testEnum = value; } - } - - private TestEnum testEnum = TestEnum.One; - - public TestEnum1 TestEnum1 - { - get { return testEnum1; } - set { testEnum1 = value; } - } - - private TestEnum1 testEnum1 = TestEnum1.Two; - - public TestEnum2 TestEnum2 - { - get { return testEnum2; } - set { testEnum2 = value; } - } - - private TestEnum2 testEnum2 = TestEnum2.One; - } -} -"@ - Add-Type $src - $op = new-object Bug378368.Test | convertto-json | convertfrom-json - $op.TestEnum | Should Be "One" - $op.TestEnum1 | Should Be "Two" - $op.TestEnum2 | Should Be 1 - } - - It "Test followup for Windows 8 bug 121627" { - - $JsonString = Get-Command Get-help |Select-Object Name, Noun, Verb| ConvertTo-Json - $actual = ConvertFrom-Json $JsonString - - $actual.Name | Should Be "Get-Help" - $actual.Noun | Should Be "Help" - $actual.Verb | Should Be "Get" - } - } - - Context "ConvertFrom and ConvertTo on JsonObject Tests" { - - It "Convert dictionary to PSObject" { - - $response = ConvertFrom-Json '{"d":{"__type":"SimpleJsonObject","Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' - $response.d.Name.First | Should Match "Joel" - } - - It "Convert to Json using PSObject" -pending:($IsCore) { - - $response = ConvertFrom-Json '{"d":{"__type":"SimpleJsonObject","Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' - - $response2 = ConvertTo-Json -InputObject $response -ErrorAction Continue - $response2 = ConvertTo-Json -InputObject $response -ErrorAction Inquire - $response2 = ConvertTo-Json -InputObject $response -ErrorAction SilentlyContinue - $response2 = ConvertTo-Json -InputObject $response -Depth 2 -Compress - $response2 | Should Be '{"d":{"Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' - - $response2 = ConvertTo-Json -InputObject $response -Depth 1 -Compress - $nameString = [System.Management.Automation.LanguagePrimitives]::ConvertTo($response.d.Name, [string]) - $response2 | Should Be "{`"d`":{`"Name`":`"$nameString`",`"Greeting`":`"Hello`"}}" - - $result1 = @" -{ - "d": { - "Name": { - "First": "Joel", - "Last": "Wood" - }, - "Greeting": "Hello" - } -} -"@ - $response2 = ConvertTo-Json -InputObject $response -Depth 2 - $response2 | Should Match $result1 - - $result2 = @" -{ - "d": { - "Name": "$nameString", - "Greeting": "Hello" - } -} -"@ - $response2 = ConvertTo-Json -InputObject $response -Depth 1 - $response2 | Should Match $result2 - - $arraylist = new-Object System.Collections.ArrayList - [void]$arraylist.Add("one") - [void]$arraylist.Add("two") - [void]$arraylist.Add("three") - $response2 = ConvertTo-Json -InputObject $arraylist -Compress - $response2 | Should Be '["one","two","three"]' - - $result3 = @" -[ - "one", - "two", - "three" -] -"@ - $response2 = ConvertTo-Json -InputObject $arraylist - $response2 | Should Be $result3 - - $response2 = $arraylist | ConvertTo-Json - $response2 | Should Be $result3 - } - - It "Convert to Json using hashtable" -pending:($IsCore) { - - $nameHash = @{First="Joe1";Last="Wood"} - $dHash = @{Name=$nameHash; Greeting="Hello"} - $rootHash = @{d=$dHash} - $response3 = ConvertTo-Json -InputObject $rootHash -Depth 2 -Compress - $response3 | Should Be '{"d":{"Greeting":"Hello","Name":{"Last":"Wood","First":"Joe1"}}}' - - $response3 = ConvertTo-Json -InputObject $rootHash -Depth 1 -Compress - $response3 | Should Be '{"d":{"Greeting":"Hello","Name":"System.Collections.Hashtable"}}' - - $result4 = @" -{ - "d": { - "Greeting": "Hello", - "Name": { - "Last": "Wood", - "First": "Joe1" - } - } -} -"@ - $response3 = ConvertTo-Json -InputObject $rootHash -Depth 2 - $response3 | Should Be $result4 - - $result5 = @" -{ - "d": { - "Greeting": "Hello", - "Name": "System.Collections.Hashtable" - } -} -"@ - $response3 = ConvertTo-Json -InputObject $rootHash -Depth 1 - $response3 | Should Be $result5 - } - - It "Convert from Json allows an empty string" { - - $emptyStringResult = ConvertFrom-Json "" - $emptyStringResult | Should Be $null - } - } - - Context "JsonObject Tests" { - - It "AddMember on JsonObject" { - - # create a Version object - $versionObject = New-Object System.Version 2, 3, 4, 14 - - # add a NoteProperty member called Note with a text note - $versionObject | Add-Member -MemberType NoteProperty -Name Note -Value "a version object" - - # add an AliasProperty called Rev as an alias to the Revison property - $versionObject | Add-Member -MemberType AliasProperty -Name Rev -Value Revision - - # add a ScriptProperty called IsOld which returns whether the version is an older version - $versionObject | Add-Member -MemberType ScriptProperty -Name IsOld -Value { ($this.Major -le 3) } - - $jstr = ConvertTo-Json $versionObject - - # convert the JSON string to a JSON object - $json = ConvertFrom-Json $jstr - - # Check the basic properties - $json.Major | Should Be 2 - $json.Minor | Should Be 3 - $json.Build | Should Be 4 - $json.Revision | Should Be 14 - $json.Note | Should Match "a version object" - - # Check the AliasProperty - $json.Rev | Should Be $json.Revision - - # Check the ScriptProperty - $json.IsOld | Should Be $true - } - - It "ConvertFrom-Json with a key value pair" { - - $json = "{name:1}" - $result = ConvertFrom-Json $json - $result.name | Should Be 1 - } - - It "ConvertFrom-Json with a simple array" { - - $json = "[1,2,3,4,5,6]" - $result = ConvertFrom-Json $json - $result.Count | Should Be 6 - $result.GetType().BaseType.fullname | Should Be "System.Array" - } - - It "ConvertFrom-Json with a float value" { - - $json = '{"SampleFloat1":1.2345E67, "SampleFloat2":-7.6543E-12}' - $result = ConvertFrom-Json $json - - $sampleFloat1 = Invoke-Expression 1.2345E67 - $result.SampleFloat1 | Should Be $sampleFloat1 - - $sampleFloat2 = Invoke-Expression -7.6543E-12 - $result.SampleFloat2 | Should Be $sampleFloat2 - } - - It "ConvertFrom-Json hash table nested in array" { - - $json = "['one', 'two', {'First':1,'Second':2,'Third':['Five','Six', 'Seven']}, 'four']" - $result = ConvertFrom-Json $json - - $result.Count | Should Be 4 - $result[0] | Should Be "one" - $result[1] | Should Be "two" - $result[3] | Should Be "four" - - $hash = $result[2] - $hash.First | Should Be 1 - $hash.Second | Should Be 2 - $hash.Third.Count | Should Be 3 - $hash.Third[0] | Should Be "Five" - $hash.Third[1] | Should Be "Six" - $hash.Third[2] | Should Be "Seven" - } - - It "ConvertFrom-Json array nested in hash table" { - - $json = '{"First":["one", "two", "three"], "Second":["four", "five"], "Third": {"blah": 4}}' - $result = ConvertFrom-Json $json - - $result.First.Count | Should Be 3 - $result.First[0] | Should Be "one" - $result.First[1] | Should Be "two" - $result.First[2] | Should Be "three" - - $result.Second.Count | Should Be 2 - $result.Second[0] | Should Be "four" - $result.Second[1] | Should Be "five" - - $result.Third.blah | Should Be "4" - } - - It "ConvertFrom-Json case insensitive test" { - - $json = '{"sAMPleValUE":12345}' - $result = ConvertFrom-Json $json - - $result.SampleValue | Should Be 12345 - } - - - It "ConvertFrom-Json sample values" { - - $json = '{"SampleInt":98765, "SampleString":"stringVal","SampleArray":[2,"two"], "SampleTrue":true, "SampleFalse":false,"SampleNull":null, "SampleFloat":9.8765E43}' - $result = ConvertFrom-Json $json - - # Validate the result object - ValidateSampleObject -result $result - - - $json = '{"SampleInt":98765, "SampleString":"stringVal","SampleArray":[2,"two"], "SampleTrue":true, ' + - '"SampleFalse":false,"SampleNull":null, "SampleFloat":9.8765E43, "SampleObject":'+ - '{"SampleInt":98765, "SampleString":"stringVal","SampleArray":[2,"two"], '+ - '"SampleTrue":true, "SampleFalse":false,"SampleNull":null, "SampleFloat":9.8765E43}}' - - # Validate the result object - $result = ConvertFrom-Json $json - ValidateSampleObject -result $result -hasEmbeddedSampleObject - } - - It "ConvertFrom-Json with special characters" { - - $json = '{"SampleValue":"\"\\\b\f\n\r\t\u4321\uD7FF"}' - $result = ConvertFrom-Json $json - $result.SampleValue[0] | Should Be '"' - $result.SampleValue[1] | Should Be '\' - $result.SampleValue[2] | Should Be 0x8 - $result.SampleValue[3] | Should Be 0xC - $result.SampleValue[4] | Should Be 0xA - $result.SampleValue[5] | Should Be 0xD - $result.SampleValue[6] | Should Be 0x9 - $result.SampleValue[7] | Should Be 0x4321 - $result.SampleValue[8] | Should Be 0xD7FF - } - } -} - -# This Describe is for new Json tests -# -Describe "Validate Json serialization" -Tags "CI" { - - Context "Validate Json serialization ascii values" { - - $testCases = @( - @{ - TestInput = 0 - ToJson = if ( $IsCore ) { '"\u0000"' } else { 'null' } - FromJson = '' - } - @{ - TestInput = 1 - ToJson = '"\u0001"' - FromJson = '' - } - @{ - TestInput = 2 - ToJson = '"\u0002"' - FromJson = '' - } - @{ - TestInput = 3 - ToJson = '"\u0003"' - FromJson = '' - } - @{ - TestInput = 4 - ToJson = '"\u0004"' - FromJson = '' - } - @{ - TestInput = 5 - ToJson = '"\u0005"' - FromJson = '' - } - @{ - TestInput = 6 - ToJson = '"\u0006"' - FromJson = '' - } - @{ - TestInput = 7 - ToJson = '"\u0007"' - FromJson = '' - } - @{ - TestInput = 8 - ToJson = '"\b"' - FromJson = '' - } - @{ - TestInput = 9 - ToJson = '"\t"' - FromJson = ' ' - } - @{ - TestInput = 10 - ToJson = '"\n"' - FromJson = "`n" - } - @{ - TestInput = 11 - ToJson = '"\u000b"' - FromJson = ' ' - } - @{ - TestInput = 12 - ToJson = '"\f"' - FromJson = ' ' - } - @{ - TestInput = 13 - ToJson = '"\r"' - FromJson = '' - } - @{ - TestInput = 14 - ToJson = '"\u000e"' - FromJson = '' - } - @{ - TestInput = 15 - ToJson = '"\u000f"' - FromJson = '' - } - @{ - TestInput = 16 - ToJson = '"\u0010"' - FromJson = '' - } - @{ - TestInput = 17 - ToJson = '"\u0011"' - FromJson = '' - } - @{ - TestInput = 18 - ToJson = '"\u0012"' - FromJson = '' - } - @{ - TestInput = 19 - ToJson = '"\u0013"' - FromJson = '' - } - @{ - TestInput = 20 - ToJson = '"\u0014"' - FromJson = '' - } - @{ - TestInput = 21 - ToJson = '"\u0015"' - FromJson = '' - } - @{ - TestInput = 22 - ToJson = '"\u0016"' - FromJson = '' - } - @{ - TestInput = 23 - ToJson = '"\u0017"' - FromJson = '' - } - @{ - TestInput = 24 - ToJson = '"\u0018"' - FromJson = '' - } - @{ - TestInput = 25 - ToJson = '"\u0019"' - FromJson = '' - } - @{ - TestInput = 26 - ToJson = '"\u001a"' - FromJson = '' - } - @{ - TestInput = 27 - ToJson = '"\u001b"' - FromJson = '' - } - @{ - TestInput = 28 - ToJson = '"\u001c"' - FromJson = '' - } - @{ - TestInput = 29 - ToJson = '"\u001d"' - FromJson = '' - } - @{ - TestInput = 30 - ToJson = '"\u001e"' - FromJson = '' - } - @{ - TestInput = 31 - ToJson = '"\u001f"' - FromJson = '' - } - @{ - TestInput = 32 - ToJson = '" "' - FromJson = ' ' - } - @{ - TestInput = 33 - ToJson = '"!"' - FromJson = '!' - } - @{ - TestInput = 34 - ToJson = '"\""' - FromJson = '"' - } - @{ - TestInput = 35 - ToJson = '"#"' - FromJson = '#' - } - @{ - TestInput = 36 - ToJson = '"$"' - FromJson = '$' - } - @{ - TestInput = 37 - ToJson = '"%"' - FromJson = '%' - } - @{ - TestInput = 38 - ToJson = if ( $IsCore ) { '"&"' } else { '"\u0026"' } - FromJson = '&' - } - @{ - TestInput = 39 - ToJson = if ( $IsCore ) { '"''"' } else { '"\u0027"' } - FromJson = "'" - } - @{ - TestInput = 40 - ToJson = '"("' - FromJson = '(' - } - @{ - TestInput = 41 - ToJson = '")"' - FromJson = ')' - } - @{ - TestInput = 42 - ToJson = '"*"' - FromJson = '*' - } - @{ - TestInput = 43 - ToJson = '"+"' - FromJson = '+' - } - @{ - TestInput = 44 - ToJson = '","' - FromJson = ',' - } - @{ - TestInput = 45 - ToJson = '"-"' - FromJson = '-' - } - @{ - TestInput = 46 - ToJson = '"."' - FromJson = '.' - } - @{ - TestInput = 47 - ToJson = '"/"' - FromJson = '/' - } - @{ - TestInput = 48 - ToJson = '"0"' - FromJson = '0' - } - @{ - TestInput = 49 - ToJson = '"1"' - FromJson = '1' - } - @{ - TestInput = 50 - ToJson = '"2"' - FromJson = '2' - } - @{ - TestInput = 51 - ToJson = '"3"' - FromJson = '3' - } - @{ - TestInput = 52 - ToJson = '"4"' - FromJson = '4' - } - @{ - TestInput = 53 - ToJson = '"5"' - FromJson = '5' - } - @{ - TestInput = 54 - ToJson = '"6"' - FromJson = '6' - } - @{ - TestInput = 55 - ToJson = '"7"' - FromJson = '7' - } - @{ - TestInput = 56 - ToJson = '"8"' - FromJson = '8' - } - @{ - TestInput = 57 - ToJson = '"9"' - FromJson = '9' - } - @{ - TestInput = 58 - ToJson = '":"' - FromJson = ':' - } - @{ - TestInput = 59 - ToJson = '";"' - FromJson = ';' - } - @{ - TestInput = 60 - ToJson = if ( $IsCore ) { '"<"' } else { '"\u003c"' } - FromJson = '<' - } - @{ - TestInput = 61 - ToJson = '"="' - FromJson = '=' - } - @{ - TestInput = 62 - ToJson = if ( $IsCore ) { '">"' } else { '"\u003e"' } - FromJson = '>' - } - @{ - TestInput = 63 - ToJson = '"?"' - FromJson = '?' - } - @{ - TestInput = 64 - ToJson = '"@"' - FromJson = '@' - } - @{ - TestInput = 65 - ToJson = '"A"' - FromJson = 'A' - } - @{ - TestInput = 66 - ToJson = '"B"' - FromJson = 'B' - } - @{ - TestInput = 67 - ToJson = '"C"' - FromJson = 'C' - } - @{ - TestInput = 68 - ToJson = '"D"' - FromJson = 'D' - } - @{ - TestInput = 69 - ToJson = '"E"' - FromJson = 'E' - } - @{ - TestInput = 70 - ToJson = '"F"' - FromJson = 'F' - } - @{ - TestInput = 71 - ToJson = '"G"' - FromJson = 'G' - } - @{ - TestInput = 72 - ToJson = '"H"' - FromJson = 'H' - } - @{ - TestInput = 73 - ToJson = '"I"' - FromJson = 'I' - } - @{ - TestInput = 74 - ToJson = '"J"' - FromJson = 'J' - } - @{ - TestInput = 75 - ToJson = '"K"' - FromJson = 'K' - } - @{ - TestInput = 76 - ToJson = '"L"' - FromJson = 'L' - } - @{ - TestInput = 77 - ToJson = '"M"' - FromJson = 'M' - } - @{ - TestInput = 78 - ToJson = '"N"' - FromJson = 'N' - } - @{ - TestInput = 79 - ToJson = '"O"' - FromJson = 'O' - } - @{ - TestInput = 80 - ToJson = '"P"' - FromJson = 'P' - } - @{ - TestInput = 81 - ToJson = '"Q"' - FromJson = 'Q' - } - @{ - TestInput = 82 - ToJson = '"R"' - FromJson = 'R' - } - @{ - TestInput = 83 - ToJson = '"S"' - FromJson = 'S' - } - @{ - TestInput = 84 - ToJson = '"T"' - FromJson = 'T' - } - @{ - TestInput = 85 - ToJson = '"U"' - FromJson = 'U' - } - @{ - TestInput = 86 - ToJson = '"V"' - FromJson = 'V' - } - @{ - TestInput = 87 - ToJson = '"W"' - FromJson = 'W' - } - @{ - TestInput = 88 - ToJson = '"X"' - FromJson = 'X' - } - @{ - TestInput = 89 - ToJson = '"Y"' - FromJson = 'Y' - } - @{ - TestInput = 90 - ToJson = '"Z"' - FromJson = 'Z' - } - @{ - TestInput = 91 - ToJson = '"["' - FromJson = '[' - } - @{ - TestInput = 92 - ToJson = '"\\"' - FromJson = '\' - } - @{ - TestInput = 93 - ToJson = '"]"' - FromJson = ']' - } - @{ - TestInput = 94 - ToJson = '"^"' - FromJson = '^' - } - @{ - TestInput = 95 - ToJson = '"_"' - FromJson = '_' - } - @{ - TestInput = 96 - ToJson = '"`"' - FromJson = '`' - } - @{ - TestInput = 97 - ToJson = '"a"' - FromJson = 'a' - } - @{ - TestInput = 98 - ToJson = '"b"' - FromJson = 'b' - } - @{ - TestInput = 99 - ToJson = '"c"' - FromJson = 'c' - } - @{ - TestInput = 100 - ToJson = '"d"' - FromJson = 'd' - } - @{ - TestInput = 101 - ToJson = '"e"' - FromJson = 'e' - } - @{ - TestInput = 102 - ToJson = '"f"' - FromJson = 'f' - } - @{ - TestInput = 103 - ToJson = '"g"' - FromJson = 'g' - } - @{ - TestInput = 104 - ToJson = '"h"' - FromJson = 'h' - } - @{ - TestInput = 105 - ToJson = '"i"' - FromJson = 'i' - } - @{ - TestInput = 106 - ToJson = '"j"' - FromJson = 'j' - } - @{ - TestInput = 107 - ToJson = '"k"' - FromJson = 'k' - } - @{ - TestInput = 108 - ToJson = '"l"' - FromJson = 'l' - } - @{ - TestInput = 109 - ToJson = '"m"' - FromJson = 'm' - } - @{ - TestInput = 110 - ToJson = '"n"' - FromJson = 'n' - } - @{ - TestInput = 111 - ToJson = '"o"' - FromJson = 'o' - } - @{ - TestInput = 112 - ToJson = '"p"' - FromJson = 'p' - } - @{ - TestInput = 113 - ToJson = '"q"' - FromJson = 'q' - } - @{ - TestInput = 114 - ToJson = '"r"' - FromJson = 'r' - } - @{ - TestInput = 115 - ToJson = '"s"' - FromJson = 's' - } - @{ - TestInput = 116 - ToJson = '"t"' - FromJson = 't' - } - @{ - TestInput = 117 - ToJson = '"u"' - FromJson = 'u' - } - @{ - TestInput = 118 - ToJson = '"v"' - FromJson = 'v' - } - @{ - TestInput = 119 - ToJson = '"w"' - FromJson = 'w' - } - @{ - TestInput = 120 - ToJson = '"x"' - FromJson = 'x' - } - @{ - TestInput = 121 - ToJson = '"y"' - FromJson = 'y' - } - @{ - TestInput = 122 - ToJson = '"z"' - FromJson = 'z' - } - @{ - TestInput = 123 - ToJson = '"{"' - FromJson = '{' - } - @{ - TestInput = 124 - ToJson = '"|"' - FromJson = '|' - } - @{ - TestInput = 125 - ToJson = '"}"' - FromJson = '}' - } - @{ - TestInput = 126 - ToJson = '"~"' - FromJson = '~' - } - @{ - TestInput = 127 - ToJson = '""' - FromJson = '' - } - ) - - function ValidateJsonSerializationForAsciiValues - { - param ($testCase) - - It "Validate 'ConvertTo-Json ([char]$($testCase.TestInput))', and 'ConvertTo-Json ([char]$($testCase.TestInput)) | ConvertFrom-Json'" { - - $result = @{ - ToJson = ConvertTo-Json ([char]$testCase.TestInput) - FromJson = ConvertTo-Json ([char]$testCase.TestInput) | ConvertFrom-Json - } - - if ($testCase.FromJson) - { - $result.FromJson | Should Be $testCase.FromJson - } - else - { - # There are two char for which the deserialized object must be compare to the serialized one via "Should Match" - # These values are [char]0 and [char]13. - $result.FromJson | Should Match $testCase.FromJson - } - $result.ToJson | Should Be $testCase.ToJson - } - } - - foreach ($testCase in $testCases) - { - ValidateJsonSerializationForAsciiValues $testCase - } - } - - Context "Validate Json serialization for types" { - - $testCases = @( - - ## Decimal types - Decimals are a 128-bit data type - @{ - TestInput = '[decimal]::MinValue' - FromJson = [decimal]::MinValue - ToJson = [decimal]::MinValue - } - @{ - TestInput = '[decimal]::MaxValue' - FromJson = [decimal]::MaxValue - ToJson = [decimal]::MaxValue - } - - # An sbyte is a signed 8-bit integer, and it ranges from -128 to 127. - # A byte is an unsigned 8-bit integer that ranges from 0 to 255 - @{ - TestInput = '[byte]::MinValue' - FromJson = [byte]::MinValue - ToJson = [byte]::MinValue - } - @{ - TestInput = '[byte]::MaxValue' - FromJson = [byte]::MaxValue - ToJson = [byte]::MaxValue - } - @{ - TestInput = '[sbyte]::MinValue' - FromJson = [sbyte]::MinValue - ToJson = [sbyte]::MinValue - } - @{ - TestInput = '[sbyte]::MaxValue' - FromJson = [sbyte]::MaxValue - ToJson = [sbyte]::MaxValue - } - @{ - TestInput = '[char]::MinValue' - FromJson = $null - ToJson = 'null' - } - @{ - TestInput = '[char]::MaxValue - 1' - FromJson = [char]::MaxValue - 1 - ToJson = [char]::MaxValue - 1 - } - @{ - TestInput = '[string]::Empty' - FromJson = [string]::Empty - ToJson = '""' - } - @{ - TestInput = '[string]"hello"' - FromJson = [string]"hello" - ToJson = '"hello"' - } - - # Int, int32, uint32, uint16, int16 - - # 32-bit signed integer - @{ - TestInput = '[int]::MaxValue' - FromJson = [int]::MaxValue - ToJson = [int]::MaxValue - } - @{ - TestInput = '[int]::MinValue' - FromJson = [int]::MinValue - ToJson = [int]::MinValue - } - @{ - TestInput = '[int32]::MaxValue' - FromJson = [int32]::MaxValue - ToJson = [int32]::MaxValue - } - @{ - TestInput = '[int32]::MinValue' - FromJson = [int32]::MinValue - ToJson = [int32]::MinValue - } - - # 32-bit unsigned integer - @{ - TestInput = '[uint32]::MaxValue' - FromJson = [uint32]::MaxValue - ToJson = [uint32]::MaxValue - } - @{ - TestInput = '[uint32]::MinValue' - FromJson = [uint32]::MinValue - ToJson = [uint32]::MinValue - } - - # 16-bit unsigned integer - @{ - TestInput = '[int16]::MinValue' - FromJson = [int16]::MinValue - ToJson = [int16]::MinValue - } - @{ - TestInput = '[uint16]::MaxValue' - FromJson = [uint16]::MaxValue - ToJson = [uint16]::MaxValue - } - - # 64-bit unsigned integer - @{ - TestInput = '[uint64]::MinValue' - FromJson = [uint64]::MinValue - ToJson = [uint64]::MinValue - } - @{ - TestInput = '[uint64]::MinValue' - FromJson = [uint64]::MinValue - ToJson = [uint64]::MinValue - } - - # 64 bit signed integer - @{ - TestInput = '[int64]::MaxValue' - FromJson = [int64]::MaxValue - ToJson = [int64]::MaxValue - } - @{ - TestInput = '[int64]::MinValue' - FromJson = [int64]::MinValue - ToJson = [int64]::MinValue - } - @{ - TestInput = '[long]::MaxValue' - FromJson = [long]::MaxValue - ToJson = [long]::MaxValue - } - @{ - TestInput = '[long]::MinValue' - FromJson = [long]::MinValue - ToJson = [long]::MinValue - } - - # Bool - @{ - TestInput = '[bool](1)' - FromJson = [bool](1) - ToJson = $true - } - @{ - TestInput = '[bool](0)' - FromJson = $false - ToJson = 'False' - } - - # Decimal - @{ - TestInput = '[decimal]::MaxValue' - FromJson = [decimal]::MaxValue - ToJson = [decimal]::MaxValue - } - @{ - TestInput = '[decimal]::MinValue' - FromJson = [decimal]::MinValue - ToJson = [decimal]::MinValue - } - - # Single - @{ - TestInput = '[single]::MaxValue' - FromJson = "3.40282347E+38" - ToJson = "3.40282347E+38" - } - @{ - TestInput = '[single]::MinValue' - FromJson = "-3.40282347E+38" - ToJson = "-3.40282347E+38" - } - - # Double - @{ - TestInput = '[double]::MaxValue' - FromJson = [double]::MaxValue - ToJson = [double]::MaxValue - } - @{ - TestInput = '[double]::MinValue' - FromJson = [double]::MinValue - ToJson = [double]::MinValue - } - ) - - function ValidateJsonSerialization - { - param ($testCase) - - if ( $TestCase.TestInput -eq "[char]::MinValue" ) { $pending = $true } else { $pending = $false } - It "Validate '$($testCase.TestInput) | ConvertTo-Json' and '$($testCase.TestInput) | ConvertTo-Json | ConvertFrom-Json'" -pending:$pending { - - # The test case input is executed via invoke-expression. Then, we use this value as an input to ConvertTo-Json, - # and the result is saved into in the $result.ToJson variable. Lastly, this value is deserialized back using - # ConvertFrom-Json, and the value is saved to $result.FromJson for comparison. - - $expression = Invoke-Expression $testCase.TestInput - $result = @{ - ToJson = $expression | ConvertTo-Json - FromJson = $expression | ConvertTo-Json | ConvertFrom-Json - } - - $result.ToJson | Should Be $testCase.ToJson - $result.FromJson | Should Be $testCase.FromJson - } - } - - foreach ($testCase in $testCases) - { - ValidateJsonSerialization $testCase - } - } - - - Context "Validate Json Serialization for 'Get-CimClass' and 'Get-Command'" { - - function ValidateProperties - { - param ( - $serialized, - $expected, - $properties - ) - - # Validate that the two collections are the same size. - $expected.Count | Should Be $serialized.Count - - for ($index = 0; $index -lt $serialized.Count; $index++) - { - $serializedObject = $serialized[$index] - $expectedObject = $expected[$index] - foreach ($property in $properties) - { - # Write-Verbose "Validating $property" -Verbose - if ($property -eq "Qualifiers") - { - $serializedObject.$property.Count | Should Be $expectedObject.$property.Count - } - else - { - $serializedObject.$property | Should Be $expectedObject.$property - } - } - } - } - - It "Validate that CimClass Properties for win32_bios can be serialized using ConvertTo-Json and ConvertFrom-Json" -skip { - - $class = Get-CimClass win32_bios - - $result = @{ - Expected = $class.CimClassProperties | ForEach-Object {$_} - SerializedViaJson = $class.CimClassProperties | ConvertTo-Json -Depth 10 | ConvertFrom-Json - } - - $propertiesToValidate = @("Name", "Flags", "Qualifiers", "ReferenceClassName") - - ValidateProperties -serialized $result.SerializedViaJson -expected $result.Expected -properties $propertiesToValidate - } - - It "Validate 'Get-Command Get-help' output with Json conversion" { - - $result = @{ - Expected = @(Get-Command Get-help) - SerializedViaJson = @(Get-Command Get-help | ConvertTo-Json | ConvertFrom-Json) - } - - $propertiesToValidate = @("Name", "Noun", "Verb") - ValidateProperties -serialized $result.SerializedViaJson -expected $result.Expected -properties $propertiesToValidate - } - - It "Validate 'Get-Command Get-Help, Get-command, Get-Member' output with Json conversion" { - - $result = @{ - Expected = @(Get-Command Get-Help, Get-Command, Get-Member) - SerializedViaJson = @(Get-Command Get-Help, Get-Command, Get-Member) | ConvertTo-Json | ConvertFrom-Json - } - - $propertiesToValidate = @("Name", "Source", "HelpFile") - ValidateProperties -serialized $result.SerializedViaJson -expected $result.Expected -properties $propertiesToValidate - } - - It "ConvertTo-JSON a dictionary of arrays" { - $a = 1..5 - $b = 6..10 - - $actual = [ordered]@{'a'=$a;'b'=$b} | ConvertTo-Json - $expected = @' -{ - "a": [ - 1, - 2, - 3, - 4, - 5 - ], - "b": [ - 6, - 7, - 8, - 9, - 10 - ] -} -'@ - $actual | Should Be $expected - } - } -} - -Describe "Json Bug fixes" -Tags "Feature" { - - function RunJsonTest - { - param ($testCase) - - It "$($testCase.Name)" { - - # Create a nested object - $start = 1 - $previous = @{ - Depth = $($testCase.NumberOfElements) - Next = $null - } - - ($($testCase.NumberOfElements)-1)..$start | foreach { - $current = @{ - Depth = $_ - Next = $previous - } - $previous = $current - } - - if ($testCase.ShouldThrow) - { - try - { - $previous | ConvertTo-Json -Depth $testCase.MaxDepth - throw "CodeExecuted" - } - catch - { - $_.FullyQualifiedErrorId | Should Be $testCase.FullyQualifiedErrorId - } - } - else - { - $theError = $null - try - { - $previous | ConvertTo-Json -Depth $testCase.MaxDepth | ConvertFrom-Json - } - catch - { - $theError = $_ - } - $theError | Should Be $null - } - } - } - - $testCases = @( - @{ - Name = "ConvertTo-Json -Depth 101 throws MaximumAllowedDepthReached when the user specifies a depth greather than 100." - NumberOfElements = 10 - MaxDepth = 101 - FullyQualifiedErrorId = "ReachedMaximumDepthAllowed,Microsoft.PowerShell.Commands.ConvertToJsonCommand" - ShouldThrow = $true - } - @{ - Name = "ConvertTo-Json and ConvertFrom-Json work for any depth less than or equal to 100." - NumberOfElements = 100 - MaxDepth = 100 - ShouldThrow = $false - } - @{ - Name = "ConvertTo-Json and ConvertFrom-Json work for depth 100 with an object larger than 100." - NumberOfElements = 105 - MaxDepth = 100 - ShouldThrow = $false - } - ) - - foreach ($testCase in $testCases) - { - RunJsonTest $testCase - } -} +# +# Copyright (c) Microsoft Corporation, 2015 +# +# This is a Pester test suite which validate the Json cmdlets. +# + +# +# This 'Describe' is for tests that were converted from utscripts (SDXROOT/admin/monad/tests/monad/DRT/utscripts) +# and C# tests (SDXROOT/admin/monad/tests/monad/DRT/commands/utility/UnitTests) to Pester. +# +Describe "Json Tests" -Tags "Feature" { + + BeforeAll { + + function ValidateSampleObject + { + param ($result, [switch]$hasEmbeddedSampleObject ) + + Write-Verbose "validating deserialized SampleObject" -Verbose + $result.SampleInt | Should Be 98765 + $result.SampleString | Should Match "stringVal" + $result.SampleArray.Count | Should Be 2 + $result.SampleTrue | Should Be $true + $result.SampleFalse | Should Be $false + $result.SampleNull | Should Be $null + $result.SampleFloat | Should Be 9.8765E+43 + + if ($hasEmbeddedSampleObject) + { + Write-Verbose "validating deserialized Embedded SampleObject" -Verbose + ValidateSampleObject -result $result.SampleObject + } + } + + } + + Context "ConvertTo-Json Bug Fixes" { + + It "ConvertTo-JSON should not have hard coded english error message" { + + # Test follow-up for bug WinBlue: 163372 - ConvertTo-JSON has hard coded english error message. + $process = Get-Process -Id $PID + $hash = @{ $process = "def" } + $expectedFullyQualifiedErrorId = "NonStringKeyInDictionary,Microsoft.PowerShell.Commands.ConvertToJsonCommand" + + try + { + ConvertTo-Json -InputObject $hash + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | should be $expectedFullyQualifiedErrorId + } + } + + It "ConvertTo-Json should handle terms with double quotes" { + + # Test follow-up for bug WinBlue: 11484 - ConvertTo-Json can't handle terms with double quotes. + + $notcompressed = ConvertTo-JSON @{ FirstName = 'Hello " World' } + $compressed = ConvertTo-Json @{ FirstName = 'Hello " World' } -Compress + $valueFromNotCompressedResult = ConvertFrom-Json -InputObject $notcompressed + $valueFromCompressedResult = ConvertFrom-Json -InputObject $compressed + + $valueFromNotCompressedResult.FirstName | Should Match $valueFromCompressedResult.FirstName + } + + It "Convertto-Json should handle Enum based on Int64" { + + # Test follow-up for bug Win8: 378368 Convertto-Json problems with Enum based on Int64. + enum TestEnum : ulong { One = 1, Two = 2 } + enum TestEnum1 : long { One = 1, Two = 2 } + enum TestEnum2 : int { One = 1, Two = 2 } + + class Test { + [TestEnum] $TestEnum = [TestEnum]::One + [TestEnum1] $TestEnum1 = [TestEnum1]::Two + [TestEnum2] $TestEnum2 = [TestEnum2]::One + } + $op = [Test]::New() | convertto-json | convertfrom-json + $op.TestEnum | Should Be "One" + $op.TestEnum1 | Should Be "Two" + $op.TestEnum2 | Should Be 1 + } + + It "Test followup for Windows 8 bug 121627" { + + $JsonString = Get-Command Get-help |Select-Object Name, Noun, Verb| ConvertTo-Json + $actual = ConvertFrom-Json $JsonString + + $actual.Name | Should Be "Get-Help" + $actual.Noun | Should Be "Help" + $actual.Verb | Should Be "Get" + } + } + + Context "ConvertFrom and ConvertTo on JsonObject Tests" { + + It "Convert dictionary to PSObject" { + + $response = ConvertFrom-Json '{"d":{"__type":"SimpleJsonObject","Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' + $response.d.Name.First | Should Match "Joel" + } + + It "Convert to Json using PSObject" -pending:($IsCore) { + + $response = ConvertFrom-Json '{"d":{"__type":"SimpleJsonObject","Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' + + $response2 = ConvertTo-Json -InputObject $response -ErrorAction Continue + $response2 = ConvertTo-Json -InputObject $response -ErrorAction Inquire + $response2 = ConvertTo-Json -InputObject $response -ErrorAction SilentlyContinue + $response2 = ConvertTo-Json -InputObject $response -Depth 2 -Compress + $response2 | Should Be '{"d":{"Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' + + $response2 = ConvertTo-Json -InputObject $response -Depth 1 -Compress + $nameString = [System.Management.Automation.LanguagePrimitives]::ConvertTo($response.d.Name, [string]) + $response2 | Should Be "{`"d`":{`"Name`":`"$nameString`",`"Greeting`":`"Hello`"}}" + + $result1 = @" +{ + "d": { + "Name": { + "First": "Joel", + "Last": "Wood" + }, + "Greeting": "Hello" + } +} +"@ + $response2 = ConvertTo-Json -InputObject $response -Depth 2 + $response2 | Should Match $result1 + + $result2 = @" +{ + "d": { + "Name": "$nameString", + "Greeting": "Hello" + } +} +"@ + $response2 = ConvertTo-Json -InputObject $response -Depth 1 + $response2 | Should Match $result2 + + $arraylist = new-Object System.Collections.ArrayList + [void]$arraylist.Add("one") + [void]$arraylist.Add("two") + [void]$arraylist.Add("three") + $response2 = ConvertTo-Json -InputObject $arraylist -Compress + $response2 | Should Be '["one","two","three"]' + + $result3 = @" +[ + "one", + "two", + "three" +] +"@ + $response2 = ConvertTo-Json -InputObject $arraylist + $response2 | Should Be $result3 + + $response2 = $arraylist | ConvertTo-Json + $response2 | Should Be $result3 + } + + It "Convert to Json using hashtable" -pending:($IsCore) { + + $nameHash = @{First="Joe1";Last="Wood"} + $dHash = @{Name=$nameHash; Greeting="Hello"} + $rootHash = @{d=$dHash} + $response3 = ConvertTo-Json -InputObject $rootHash -Depth 2 -Compress + $response3 | Should Be '{"d":{"Greeting":"Hello","Name":{"Last":"Wood","First":"Joe1"}}}' + + $response3 = ConvertTo-Json -InputObject $rootHash -Depth 1 -Compress + $response3 | Should Be '{"d":{"Greeting":"Hello","Name":"System.Collections.Hashtable"}}' + + $result4 = @" +{ + "d": { + "Greeting": "Hello", + "Name": { + "Last": "Wood", + "First": "Joe1" + } + } +} +"@ + $response3 = ConvertTo-Json -InputObject $rootHash -Depth 2 + $response3 | Should Be $result4 + + $result5 = @" +{ + "d": { + "Greeting": "Hello", + "Name": "System.Collections.Hashtable" + } +} +"@ + $response3 = ConvertTo-Json -InputObject $rootHash -Depth 1 + $response3 | Should Be $result5 + } + + It "Convert from Json allows an empty string" { + + $emptyStringResult = ConvertFrom-Json "" + $emptyStringResult | Should Be $null + } + } + + Context "JsonObject Tests" { + + It "AddMember on JsonObject" { + + # create a Version object + $versionObject = New-Object System.Version 2, 3, 4, 14 + + # add a NoteProperty member called Note with a text note + $versionObject | Add-Member -MemberType NoteProperty -Name Note -Value "a version object" + + # add an AliasProperty called Rev as an alias to the Revison property + $versionObject | Add-Member -MemberType AliasProperty -Name Rev -Value Revision + + # add a ScriptProperty called IsOld which returns whether the version is an older version + $versionObject | Add-Member -MemberType ScriptProperty -Name IsOld -Value { ($this.Major -le 3) } + + $jstr = ConvertTo-Json $versionObject + + # convert the JSON string to a JSON object + $json = ConvertFrom-Json $jstr + + # Check the basic properties + $json.Major | Should Be 2 + $json.Minor | Should Be 3 + $json.Build | Should Be 4 + $json.Revision | Should Be 14 + $json.Note | Should Match "a version object" + + # Check the AliasProperty + $json.Rev | Should Be $json.Revision + + # Check the ScriptProperty + $json.IsOld | Should Be $true + } + + It "ConvertFrom-Json with a key value pair" { + + $json = "{name:1}" + $result = ConvertFrom-Json $json + $result.name | Should Be 1 + } + + It "ConvertFrom-Json with a simple array" { + + $json = "[1,2,3,4,5,6]" + $result = ConvertFrom-Json $json + $result.Count | Should Be 6 + $result.GetType().BaseType.fullname | Should Be "System.Array" + } + + It "ConvertFrom-Json with a float value" { + + $json = '{"SampleFloat1":1.2345E67, "SampleFloat2":-7.6543E-12}' + $result = ConvertFrom-Json $json + + $sampleFloat1 = Invoke-Expression 1.2345E67 + $result.SampleFloat1 | Should Be $sampleFloat1 + + $sampleFloat2 = Invoke-Expression -7.6543E-12 + $result.SampleFloat2 | Should Be $sampleFloat2 + } + + It "ConvertFrom-Json hash table nested in array" { + + $json = "['one', 'two', {'First':1,'Second':2,'Third':['Five','Six', 'Seven']}, 'four']" + $result = ConvertFrom-Json $json + + $result.Count | Should Be 4 + $result[0] | Should Be "one" + $result[1] | Should Be "two" + $result[3] | Should Be "four" + + $hash = $result[2] + $hash.First | Should Be 1 + $hash.Second | Should Be 2 + $hash.Third.Count | Should Be 3 + $hash.Third[0] | Should Be "Five" + $hash.Third[1] | Should Be "Six" + $hash.Third[2] | Should Be "Seven" + } + + It "ConvertFrom-Json array nested in hash table" { + + $json = '{"First":["one", "two", "three"], "Second":["four", "five"], "Third": {"blah": 4}}' + $result = ConvertFrom-Json $json + + $result.First.Count | Should Be 3 + $result.First[0] | Should Be "one" + $result.First[1] | Should Be "two" + $result.First[2] | Should Be "three" + + $result.Second.Count | Should Be 2 + $result.Second[0] | Should Be "four" + $result.Second[1] | Should Be "five" + + $result.Third.blah | Should Be "4" + } + + It "ConvertFrom-Json case insensitive test" { + + $json = '{"sAMPleValUE":12345}' + $result = ConvertFrom-Json $json + + $result.SampleValue | Should Be 12345 + } + + + It "ConvertFrom-Json sample values" { + + $json = '{"SampleInt":98765, "SampleString":"stringVal","SampleArray":[2,"two"], "SampleTrue":true, "SampleFalse":false,"SampleNull":null, "SampleFloat":9.8765E43}' + $result = ConvertFrom-Json $json + + # Validate the result object + ValidateSampleObject -result $result + + + $json = '{"SampleInt":98765, "SampleString":"stringVal","SampleArray":[2,"two"], "SampleTrue":true, ' + + '"SampleFalse":false,"SampleNull":null, "SampleFloat":9.8765E43, "SampleObject":'+ + '{"SampleInt":98765, "SampleString":"stringVal","SampleArray":[2,"two"], '+ + '"SampleTrue":true, "SampleFalse":false,"SampleNull":null, "SampleFloat":9.8765E43}}' + + # Validate the result object + $result = ConvertFrom-Json $json + ValidateSampleObject -result $result -hasEmbeddedSampleObject + } + + It "ConvertFrom-Json with special characters" { + + $json = '{"SampleValue":"\"\\\b\f\n\r\t\u4321\uD7FF"}' + $result = ConvertFrom-Json $json + $result.SampleValue[0] | Should Be '"' + $result.SampleValue[1] | Should Be '\' + $result.SampleValue[2] | Should Be 0x8 + $result.SampleValue[3] | Should Be 0xC + $result.SampleValue[4] | Should Be 0xA + $result.SampleValue[5] | Should Be 0xD + $result.SampleValue[6] | Should Be 0x9 + $result.SampleValue[7] | Should Be 0x4321 + $result.SampleValue[8] | Should Be 0xD7FF + } + } +} + +# This Describe is for new Json tests +# +Describe "Validate Json serialization" -Tags "CI" { + + Context "Validate Json serialization ascii values" { + + $testCases = @( + @{ + TestInput = 0 + ToJson = if ( $IsCore ) { '"\u0000"' } else { 'null' } + FromJson = '' + } + @{ + TestInput = 1 + ToJson = '"\u0001"' + FromJson = '' + } + @{ + TestInput = 2 + ToJson = '"\u0002"' + FromJson = '' + } + @{ + TestInput = 3 + ToJson = '"\u0003"' + FromJson = '' + } + @{ + TestInput = 4 + ToJson = '"\u0004"' + FromJson = '' + } + @{ + TestInput = 5 + ToJson = '"\u0005"' + FromJson = '' + } + @{ + TestInput = 6 + ToJson = '"\u0006"' + FromJson = '' + } + @{ + TestInput = 7 + ToJson = '"\u0007"' + FromJson = '' + } + @{ + TestInput = 8 + ToJson = '"\b"' + FromJson = '' + } + @{ + TestInput = 9 + ToJson = '"\t"' + FromJson = ' ' + } + @{ + TestInput = 10 + ToJson = '"\n"' + FromJson = "`n" + } + @{ + TestInput = 11 + ToJson = '"\u000b"' + FromJson = ' ' + } + @{ + TestInput = 12 + ToJson = '"\f"' + FromJson = ' ' + } + @{ + TestInput = 13 + ToJson = '"\r"' + FromJson = '' + } + @{ + TestInput = 14 + ToJson = '"\u000e"' + FromJson = '' + } + @{ + TestInput = 15 + ToJson = '"\u000f"' + FromJson = '' + } + @{ + TestInput = 16 + ToJson = '"\u0010"' + FromJson = '' + } + @{ + TestInput = 17 + ToJson = '"\u0011"' + FromJson = '' + } + @{ + TestInput = 18 + ToJson = '"\u0012"' + FromJson = '' + } + @{ + TestInput = 19 + ToJson = '"\u0013"' + FromJson = '' + } + @{ + TestInput = 20 + ToJson = '"\u0014"' + FromJson = '' + } + @{ + TestInput = 21 + ToJson = '"\u0015"' + FromJson = '' + } + @{ + TestInput = 22 + ToJson = '"\u0016"' + FromJson = '' + } + @{ + TestInput = 23 + ToJson = '"\u0017"' + FromJson = '' + } + @{ + TestInput = 24 + ToJson = '"\u0018"' + FromJson = '' + } + @{ + TestInput = 25 + ToJson = '"\u0019"' + FromJson = '' + } + @{ + TestInput = 26 + ToJson = '"\u001a"' + FromJson = '' + } + @{ + TestInput = 27 + ToJson = '"\u001b"' + FromJson = '' + } + @{ + TestInput = 28 + ToJson = '"\u001c"' + FromJson = '' + } + @{ + TestInput = 29 + ToJson = '"\u001d"' + FromJson = '' + } + @{ + TestInput = 30 + ToJson = '"\u001e"' + FromJson = '' + } + @{ + TestInput = 31 + ToJson = '"\u001f"' + FromJson = '' + } + @{ + TestInput = 32 + ToJson = '" "' + FromJson = ' ' + } + @{ + TestInput = 33 + ToJson = '"!"' + FromJson = '!' + } + @{ + TestInput = 34 + ToJson = '"\""' + FromJson = '"' + } + @{ + TestInput = 35 + ToJson = '"#"' + FromJson = '#' + } + @{ + TestInput = 36 + ToJson = '"$"' + FromJson = '$' + } + @{ + TestInput = 37 + ToJson = '"%"' + FromJson = '%' + } + @{ + TestInput = 38 + ToJson = if ( $IsCore ) { '"&"' } else { '"\u0026"' } + FromJson = '&' + } + @{ + TestInput = 39 + ToJson = if ( $IsCore ) { '"''"' } else { '"\u0027"' } + FromJson = "'" + } + @{ + TestInput = 40 + ToJson = '"("' + FromJson = '(' + } + @{ + TestInput = 41 + ToJson = '")"' + FromJson = ')' + } + @{ + TestInput = 42 + ToJson = '"*"' + FromJson = '*' + } + @{ + TestInput = 43 + ToJson = '"+"' + FromJson = '+' + } + @{ + TestInput = 44 + ToJson = '","' + FromJson = ',' + } + @{ + TestInput = 45 + ToJson = '"-"' + FromJson = '-' + } + @{ + TestInput = 46 + ToJson = '"."' + FromJson = '.' + } + @{ + TestInput = 47 + ToJson = '"/"' + FromJson = '/' + } + @{ + TestInput = 48 + ToJson = '"0"' + FromJson = '0' + } + @{ + TestInput = 49 + ToJson = '"1"' + FromJson = '1' + } + @{ + TestInput = 50 + ToJson = '"2"' + FromJson = '2' + } + @{ + TestInput = 51 + ToJson = '"3"' + FromJson = '3' + } + @{ + TestInput = 52 + ToJson = '"4"' + FromJson = '4' + } + @{ + TestInput = 53 + ToJson = '"5"' + FromJson = '5' + } + @{ + TestInput = 54 + ToJson = '"6"' + FromJson = '6' + } + @{ + TestInput = 55 + ToJson = '"7"' + FromJson = '7' + } + @{ + TestInput = 56 + ToJson = '"8"' + FromJson = '8' + } + @{ + TestInput = 57 + ToJson = '"9"' + FromJson = '9' + } + @{ + TestInput = 58 + ToJson = '":"' + FromJson = ':' + } + @{ + TestInput = 59 + ToJson = '";"' + FromJson = ';' + } + @{ + TestInput = 60 + ToJson = if ( $IsCore ) { '"<"' } else { '"\u003c"' } + FromJson = '<' + } + @{ + TestInput = 61 + ToJson = '"="' + FromJson = '=' + } + @{ + TestInput = 62 + ToJson = if ( $IsCore ) { '">"' } else { '"\u003e"' } + FromJson = '>' + } + @{ + TestInput = 63 + ToJson = '"?"' + FromJson = '?' + } + @{ + TestInput = 64 + ToJson = '"@"' + FromJson = '@' + } + @{ + TestInput = 65 + ToJson = '"A"' + FromJson = 'A' + } + @{ + TestInput = 66 + ToJson = '"B"' + FromJson = 'B' + } + @{ + TestInput = 67 + ToJson = '"C"' + FromJson = 'C' + } + @{ + TestInput = 68 + ToJson = '"D"' + FromJson = 'D' + } + @{ + TestInput = 69 + ToJson = '"E"' + FromJson = 'E' + } + @{ + TestInput = 70 + ToJson = '"F"' + FromJson = 'F' + } + @{ + TestInput = 71 + ToJson = '"G"' + FromJson = 'G' + } + @{ + TestInput = 72 + ToJson = '"H"' + FromJson = 'H' + } + @{ + TestInput = 73 + ToJson = '"I"' + FromJson = 'I' + } + @{ + TestInput = 74 + ToJson = '"J"' + FromJson = 'J' + } + @{ + TestInput = 75 + ToJson = '"K"' + FromJson = 'K' + } + @{ + TestInput = 76 + ToJson = '"L"' + FromJson = 'L' + } + @{ + TestInput = 77 + ToJson = '"M"' + FromJson = 'M' + } + @{ + TestInput = 78 + ToJson = '"N"' + FromJson = 'N' + } + @{ + TestInput = 79 + ToJson = '"O"' + FromJson = 'O' + } + @{ + TestInput = 80 + ToJson = '"P"' + FromJson = 'P' + } + @{ + TestInput = 81 + ToJson = '"Q"' + FromJson = 'Q' + } + @{ + TestInput = 82 + ToJson = '"R"' + FromJson = 'R' + } + @{ + TestInput = 83 + ToJson = '"S"' + FromJson = 'S' + } + @{ + TestInput = 84 + ToJson = '"T"' + FromJson = 'T' + } + @{ + TestInput = 85 + ToJson = '"U"' + FromJson = 'U' + } + @{ + TestInput = 86 + ToJson = '"V"' + FromJson = 'V' + } + @{ + TestInput = 87 + ToJson = '"W"' + FromJson = 'W' + } + @{ + TestInput = 88 + ToJson = '"X"' + FromJson = 'X' + } + @{ + TestInput = 89 + ToJson = '"Y"' + FromJson = 'Y' + } + @{ + TestInput = 90 + ToJson = '"Z"' + FromJson = 'Z' + } + @{ + TestInput = 91 + ToJson = '"["' + FromJson = '[' + } + @{ + TestInput = 92 + ToJson = '"\\"' + FromJson = '\' + } + @{ + TestInput = 93 + ToJson = '"]"' + FromJson = ']' + } + @{ + TestInput = 94 + ToJson = '"^"' + FromJson = '^' + } + @{ + TestInput = 95 + ToJson = '"_"' + FromJson = '_' + } + @{ + TestInput = 96 + ToJson = '"`"' + FromJson = '`' + } + @{ + TestInput = 97 + ToJson = '"a"' + FromJson = 'a' + } + @{ + TestInput = 98 + ToJson = '"b"' + FromJson = 'b' + } + @{ + TestInput = 99 + ToJson = '"c"' + FromJson = 'c' + } + @{ + TestInput = 100 + ToJson = '"d"' + FromJson = 'd' + } + @{ + TestInput = 101 + ToJson = '"e"' + FromJson = 'e' + } + @{ + TestInput = 102 + ToJson = '"f"' + FromJson = 'f' + } + @{ + TestInput = 103 + ToJson = '"g"' + FromJson = 'g' + } + @{ + TestInput = 104 + ToJson = '"h"' + FromJson = 'h' + } + @{ + TestInput = 105 + ToJson = '"i"' + FromJson = 'i' + } + @{ + TestInput = 106 + ToJson = '"j"' + FromJson = 'j' + } + @{ + TestInput = 107 + ToJson = '"k"' + FromJson = 'k' + } + @{ + TestInput = 108 + ToJson = '"l"' + FromJson = 'l' + } + @{ + TestInput = 109 + ToJson = '"m"' + FromJson = 'm' + } + @{ + TestInput = 110 + ToJson = '"n"' + FromJson = 'n' + } + @{ + TestInput = 111 + ToJson = '"o"' + FromJson = 'o' + } + @{ + TestInput = 112 + ToJson = '"p"' + FromJson = 'p' + } + @{ + TestInput = 113 + ToJson = '"q"' + FromJson = 'q' + } + @{ + TestInput = 114 + ToJson = '"r"' + FromJson = 'r' + } + @{ + TestInput = 115 + ToJson = '"s"' + FromJson = 's' + } + @{ + TestInput = 116 + ToJson = '"t"' + FromJson = 't' + } + @{ + TestInput = 117 + ToJson = '"u"' + FromJson = 'u' + } + @{ + TestInput = 118 + ToJson = '"v"' + FromJson = 'v' + } + @{ + TestInput = 119 + ToJson = '"w"' + FromJson = 'w' + } + @{ + TestInput = 120 + ToJson = '"x"' + FromJson = 'x' + } + @{ + TestInput = 121 + ToJson = '"y"' + FromJson = 'y' + } + @{ + TestInput = 122 + ToJson = '"z"' + FromJson = 'z' + } + @{ + TestInput = 123 + ToJson = '"{"' + FromJson = '{' + } + @{ + TestInput = 124 + ToJson = '"|"' + FromJson = '|' + } + @{ + TestInput = 125 + ToJson = '"}"' + FromJson = '}' + } + @{ + TestInput = 126 + ToJson = '"~"' + FromJson = '~' + } + @{ + TestInput = 127 + ToJson = '""' + FromJson = '' + } + ) + + function ValidateJsonSerializationForAsciiValues + { + param ($testCase) + + It "Validate 'ConvertTo-Json ([char]$($testCase.TestInput))', and 'ConvertTo-Json ([char]$($testCase.TestInput)) | ConvertFrom-Json'" { + + $result = @{ + ToJson = ConvertTo-Json ([char]$testCase.TestInput) + FromJson = ConvertTo-Json ([char]$testCase.TestInput) | ConvertFrom-Json + } + + if ($testCase.FromJson) + { + $result.FromJson | Should Be $testCase.FromJson + } + else + { + # There are two char for which the deserialized object must be compare to the serialized one via "Should Match" + # These values are [char]0 and [char]13. + $result.FromJson | Should Match $testCase.FromJson + } + $result.ToJson | Should Be $testCase.ToJson + } + } + + foreach ($testCase in $testCases) + { + ValidateJsonSerializationForAsciiValues $testCase + } + } + + Context "Validate Json serialization for types" { + + $testCases = @( + + ## Decimal types - Decimals are a 128-bit data type + @{ + TestInput = '[decimal]::MinValue' + FromJson = [decimal]::MinValue + ToJson = [decimal]::MinValue + } + @{ + TestInput = '[decimal]::MaxValue' + FromJson = [decimal]::MaxValue + ToJson = [decimal]::MaxValue + } + + # An sbyte is a signed 8-bit integer, and it ranges from -128 to 127. + # A byte is an unsigned 8-bit integer that ranges from 0 to 255 + @{ + TestInput = '[byte]::MinValue' + FromJson = [byte]::MinValue + ToJson = [byte]::MinValue + } + @{ + TestInput = '[byte]::MaxValue' + FromJson = [byte]::MaxValue + ToJson = [byte]::MaxValue + } + @{ + TestInput = '[sbyte]::MinValue' + FromJson = [sbyte]::MinValue + ToJson = [sbyte]::MinValue + } + @{ + TestInput = '[sbyte]::MaxValue' + FromJson = [sbyte]::MaxValue + ToJson = [sbyte]::MaxValue + } + @{ + TestInput = '[char]::MinValue' + FromJson = $null + ToJson = 'null' + } + @{ + TestInput = '[char]::MaxValue - 1' + FromJson = [char]::MaxValue - 1 + ToJson = [char]::MaxValue - 1 + } + @{ + TestInput = '[string]::Empty' + FromJson = [string]::Empty + ToJson = '""' + } + @{ + TestInput = '[string]"hello"' + FromJson = [string]"hello" + ToJson = '"hello"' + } + + # Int, int32, uint32, uint16, int16 + + # 32-bit signed integer + @{ + TestInput = '[int]::MaxValue' + FromJson = [int]::MaxValue + ToJson = [int]::MaxValue + } + @{ + TestInput = '[int]::MinValue' + FromJson = [int]::MinValue + ToJson = [int]::MinValue + } + @{ + TestInput = '[int32]::MaxValue' + FromJson = [int32]::MaxValue + ToJson = [int32]::MaxValue + } + @{ + TestInput = '[int32]::MinValue' + FromJson = [int32]::MinValue + ToJson = [int32]::MinValue + } + + # 32-bit unsigned integer + @{ + TestInput = '[uint32]::MaxValue' + FromJson = [uint32]::MaxValue + ToJson = [uint32]::MaxValue + } + @{ + TestInput = '[uint32]::MinValue' + FromJson = [uint32]::MinValue + ToJson = [uint32]::MinValue + } + + # 16-bit unsigned integer + @{ + TestInput = '[int16]::MinValue' + FromJson = [int16]::MinValue + ToJson = [int16]::MinValue + } + @{ + TestInput = '[uint16]::MaxValue' + FromJson = [uint16]::MaxValue + ToJson = [uint16]::MaxValue + } + + # 64-bit unsigned integer + @{ + TestInput = '[uint64]::MinValue' + FromJson = [uint64]::MinValue + ToJson = [uint64]::MinValue + } + @{ + TestInput = '[uint64]::MinValue' + FromJson = [uint64]::MinValue + ToJson = [uint64]::MinValue + } + + # 64 bit signed integer + @{ + TestInput = '[int64]::MaxValue' + FromJson = [int64]::MaxValue + ToJson = [int64]::MaxValue + } + @{ + TestInput = '[int64]::MinValue' + FromJson = [int64]::MinValue + ToJson = [int64]::MinValue + } + @{ + TestInput = '[long]::MaxValue' + FromJson = [long]::MaxValue + ToJson = [long]::MaxValue + } + @{ + TestInput = '[long]::MinValue' + FromJson = [long]::MinValue + ToJson = [long]::MinValue + } + + # Bool + @{ + TestInput = '[bool](1)' + FromJson = [bool](1) + ToJson = $true + } + @{ + TestInput = '[bool](0)' + FromJson = $false + ToJson = 'False' + } + + # Decimal + @{ + TestInput = '[decimal]::MaxValue' + FromJson = [decimal]::MaxValue + ToJson = [decimal]::MaxValue + } + @{ + TestInput = '[decimal]::MinValue' + FromJson = [decimal]::MinValue + ToJson = [decimal]::MinValue + } + + # Single + @{ + TestInput = '[single]::MaxValue' + FromJson = "3.40282347E+38" + ToJson = "3.40282347E+38" + } + @{ + TestInput = '[single]::MinValue' + FromJson = "-3.40282347E+38" + ToJson = "-3.40282347E+38" + } + + # Double + @{ + TestInput = '[double]::MaxValue' + FromJson = [double]::MaxValue + ToJson = [double]::MaxValue + } + @{ + TestInput = '[double]::MinValue' + FromJson = [double]::MinValue + ToJson = [double]::MinValue + } + ) + + function ValidateJsonSerialization + { + param ($testCase) + + if ( $TestCase.TestInput -eq "[char]::MinValue" ) { $pending = $true } else { $pending = $false } + It "Validate '$($testCase.TestInput) | ConvertTo-Json' and '$($testCase.TestInput) | ConvertTo-Json | ConvertFrom-Json'" -pending:$pending { + + # The test case input is executed via invoke-expression. Then, we use this value as an input to ConvertTo-Json, + # and the result is saved into in the $result.ToJson variable. Lastly, this value is deserialized back using + # ConvertFrom-Json, and the value is saved to $result.FromJson for comparison. + + $expression = Invoke-Expression $testCase.TestInput + $result = @{ + ToJson = $expression | ConvertTo-Json + FromJson = $expression | ConvertTo-Json | ConvertFrom-Json + } + + $result.ToJson | Should Be $testCase.ToJson + $result.FromJson | Should Be $testCase.FromJson + } + } + + foreach ($testCase in $testCases) + { + ValidateJsonSerialization $testCase + } + } + + + Context "Validate Json Serialization for 'Get-CimClass' and 'Get-Command'" { + + function ValidateProperties + { + param ( + $serialized, + $expected, + $properties + ) + + # Validate that the two collections are the same size. + $expected.Count | Should Be $serialized.Count + + for ($index = 0; $index -lt $serialized.Count; $index++) + { + $serializedObject = $serialized[$index] + $expectedObject = $expected[$index] + foreach ($property in $properties) + { + # Write-Verbose "Validating $property" -Verbose + if ($property -eq "Qualifiers") + { + $serializedObject.$property.Count | Should Be $expectedObject.$property.Count + } + else + { + $serializedObject.$property | Should Be $expectedObject.$property + } + } + } + } + + It "Validate that CimClass Properties for win32_bios can be serialized using ConvertTo-Json and ConvertFrom-Json" -skip { + + $class = Get-CimClass win32_bios + + $result = @{ + Expected = $class.CimClassProperties | ForEach-Object {$_} + SerializedViaJson = $class.CimClassProperties | ConvertTo-Json -Depth 10 | ConvertFrom-Json + } + + $propertiesToValidate = @("Name", "Flags", "Qualifiers", "ReferenceClassName") + + ValidateProperties -serialized $result.SerializedViaJson -expected $result.Expected -properties $propertiesToValidate + } + + It "Validate 'Get-Command Get-help' output with Json conversion" { + + $result = @{ + Expected = @(Get-Command Get-help) + SerializedViaJson = @(Get-Command Get-help | ConvertTo-Json | ConvertFrom-Json) + } + + $propertiesToValidate = @("Name", "Noun", "Verb") + ValidateProperties -serialized $result.SerializedViaJson -expected $result.Expected -properties $propertiesToValidate + } + + It "Validate 'Get-Command Get-Help, Get-command, Get-Member' output with Json conversion" { + + $result = @{ + Expected = @(Get-Command Get-Help, Get-Command, Get-Member) + SerializedViaJson = @(Get-Command Get-Help, Get-Command, Get-Member) | ConvertTo-Json | ConvertFrom-Json + } + + $propertiesToValidate = @("Name", "Source", "HelpFile") + ValidateProperties -serialized $result.SerializedViaJson -expected $result.Expected -properties $propertiesToValidate + } + + It "ConvertTo-JSON a dictionary of arrays" { + $a = 1..5 + $b = 6..10 + + $actual = [ordered]@{'a'=$a;'b'=$b} | ConvertTo-Json + $expected = @' +{ + "a": [ + 1, + 2, + 3, + 4, + 5 + ], + "b": [ + 6, + 7, + 8, + 9, + 10 + ] +} +'@ + $actual | Should Be $expected + } + } +} + +Describe "Json Bug fixes" -Tags "Feature" { + + function RunJsonTest + { + param ($testCase) + + It "$($testCase.Name)" { + + # Create a nested object + $start = 1 + $previous = @{ + Depth = $($testCase.NumberOfElements) + Next = $null + } + + ($($testCase.NumberOfElements)-1)..$start | foreach { + $current = @{ + Depth = $_ + Next = $previous + } + $previous = $current + } + + if ($testCase.ShouldThrow) + { + try + { + $previous | ConvertTo-Json -Depth $testCase.MaxDepth + throw "CodeExecuted" + } + catch + { + $_.FullyQualifiedErrorId | Should Be $testCase.FullyQualifiedErrorId + } + } + else + { + $theError = $null + try + { + $previous | ConvertTo-Json -Depth $testCase.MaxDepth | ConvertFrom-Json + } + catch + { + $theError = $_ + } + $theError | Should Be $null + } + } + } + + $testCases = @( + @{ + Name = "ConvertTo-Json -Depth 101 throws MaximumAllowedDepthReached when the user specifies a depth greather than 100." + NumberOfElements = 10 + MaxDepth = 101 + FullyQualifiedErrorId = "ReachedMaximumDepthAllowed,Microsoft.PowerShell.Commands.ConvertToJsonCommand" + ShouldThrow = $true + } + @{ + Name = "ConvertTo-Json and ConvertFrom-Json work for any depth less than or equal to 100." + NumberOfElements = 100 + MaxDepth = 100 + ShouldThrow = $false + } + @{ + Name = "ConvertTo-Json and ConvertFrom-Json work for depth 100 with an object larger than 100." + NumberOfElements = 105 + MaxDepth = 100 + ShouldThrow = $false + } + ) + + foreach ($testCase in $testCases) + { + RunJsonTest $testCase + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 index f26a7e4c8..5bdb79537 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 @@ -1,86 +1,86 @@ -Describe "Tests for the Import-PowerShellDataFile cmdlet" -Tags "Feature" { - - It "Validates error on a missing path" { - - $foundError = "" - try - { - Import-PowerShellDataFile -Path /SomeMissingDirectory -ErrorAction Stop - } - catch - { - $foundError = $_.FullyQualifiedErrorId - } - - $foundError | Should be "PathNotFound,Microsoft.PowerShell.Commands.ResolvePathCommand" - } - - It "Validates error on a directory" { - - $foundError = "" - try - { - Import-PowerShellDataFile ${TESTDRIVE} -ErrorAction Stop - } - catch - { - $foundError = $_.FullyQualifiedErrorId - } - - $foundError | Should be "CouldNotParseAsPowerShellDataFile,Import-PowerShellDataFile" - } - - It "Generates a good error on an insecure file" { - - $path = New-TemporaryFile - Set-Content $path '@{ Foo = Get-Process }' - - $foundError = "" - try - { - Import-PowerShellDataFile $path -ErrorAction Stop - } - catch - { - $foundError = $_.FullyQualifiedErrorId - } - finally - { - Remove-Item $path - } - - $foundError | Should be "InvalidOperationException,Import-PowerShellDataFile" - } - - It "Generates a good error on a file that isn't a PowerShell Data File (missing the hashtable root)" { - - $path = New-TemporaryFile - Set-Content $path '"Hello World"' - - $foundError = "" - try - { - Import-PowerShellDataFile $path -ErrorAction Stop - } - catch - { - $foundError = $_.FullyQualifiedErrorId - } - finally - { - Remove-Item $path - } - - $foundError | Should be "CouldNotParseAsPowerShellDataFileNoHashtableRoot,Import-PowerShellDataFile" - } - - It "Can parse a PowerShell Data File (detailed tests are in AST.SafeGetValue tests)" { - - $path = New-TemporaryFile - Set-Content $path '@{ "Hello" = "World" }' - - $result = Import-PowerShellDataFile $path -ErrorAction Stop - $result.Hello | Should be "World" - } - -} +Describe "Tests for the Import-PowerShellDataFile cmdlet" -Tags "Feature" { + + It "Validates error on a missing path" { + + $foundError = "" + try + { + Import-PowerShellDataFile -Path /SomeMissingDirectory -ErrorAction Stop + } + catch + { + $foundError = $_.FullyQualifiedErrorId + } + + $foundError | Should be "PathNotFound,Microsoft.PowerShell.Commands.ResolvePathCommand" + } + + It "Validates error on a directory" { + + $foundError = "" + try + { + Import-PowerShellDataFile ${TESTDRIVE} -ErrorAction Stop + } + catch + { + $foundError = $_.FullyQualifiedErrorId + } + + $foundError | Should be "CouldNotParseAsPowerShellDataFile,Import-PowerShellDataFile" + } + + It "Generates a good error on an insecure file" { + + $path = New-TemporaryFile + Set-Content $path '@{ Foo = Get-Process }' + + $foundError = "" + try + { + Import-PowerShellDataFile $path -ErrorAction Stop + } + catch + { + $foundError = $_.FullyQualifiedErrorId + } + finally + { + Remove-Item $path + } + + $foundError | Should be "InvalidOperationException,Import-PowerShellDataFile" + } + + It "Generates a good error on a file that isn't a PowerShell Data File (missing the hashtable root)" { + + $path = New-TemporaryFile + Set-Content $path '"Hello World"' + + $foundError = "" + try + { + Import-PowerShellDataFile $path -ErrorAction Stop + } + catch + { + $foundError = $_.FullyQualifiedErrorId + } + finally + { + Remove-Item $path + } + + $foundError | Should be "CouldNotParseAsPowerShellDataFileNoHashtableRoot,Import-PowerShellDataFile" + } + + It "Can parse a PowerShell Data File (detailed tests are in AST.SafeGetValue tests)" { + + $path = New-TemporaryFile + Set-Content $path '@{ "Hello" = "World" }' + + $result = Import-PowerShellDataFile $path -ErrorAction Stop + $result.Hello | Should be "World" + } + +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/alias.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/alias.tests.ps1 index 2ed3956d6..4317e8d21 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/alias.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/alias.tests.ps1 @@ -1,160 +1,160 @@ -Describe "Alias tests" -Tags "CI" { - - BeforeAll { - $testPath = Join-Path testdrive:\ ("testAlias\[.test") - New-Item -ItemType Directory -Path $testPath -Force | Out-Null - - class TestData - { - [string] $testName - [string] $testFile - [string] $expectedError - - TestData($name, $file, $error) - { - $this.testName = $name - $this.testFile = $file - $this.expectedError = $error - } - } - } - - Context "Export-Alias literal path" { - BeforeAll { - $csvFile = Join-Path $testPath "alias.csv" - $ps1File = Join-Path $testPath "alias.ps1" - - $testCases = @() - $testCases += [TestData]::new("CSV", $csvFile, [NullString]::Value) - $testCases += [TestData]::new("PS1", $ps1File, [NullString]::Value) - $testCases += [TestData]::new("Empty string", "", "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ExportAliasCommand") - $testCases += [TestData]::new("Null", [NullString]::Value, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportAliasCommand") - $testCases += [TestData]::new("Non filesystem provider", 'cert:\alias.ps1', "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ExportAliasCommand") - } - - $testCases | % { - - It "for $($_.testName)" { - - $test = $_ - try - { - Export-Alias -LiteralPath $test.testFile -ErrorAction SilentlyContinue - } - catch - { - $exportAliasError = $_ - } - - if($test.expectedError -eq $null) - { - Test-Path -LiteralPath $test.testFile | Should Be $true - } - else - { - $exportAliasError.FullyqualifiedErrorId | Should Be $test.expectedError - } - } - - AfterEach { - Remove-Item -LiteralPath $test.testFile -Force -ErrorAction SilentlyContinue - } - } - - It "when file exists with NoClobber" { - Export-Alias -LiteralPath $csvFile - - try - { - Export-Alias -LiteralPath $csvFile -NoClobber - } - catch - { - $exportAliasError = $_ - } - - $exportAliasError.FullyQualifiedErrorId | Should Be "NoClobber,Microsoft.PowerShell.Commands.ExportAliasCommand" - } - } - - Context "Export-All inside a literal path" { - BeforeEach { - Push-Location -LiteralPath $testPath - } - - It "with a CSV file" { - Export-Alias "alias.csv" - Test-Path -LiteralPath (Join-Path $testPath "alias.csv") | Should Be $true - } - - It "with NoClobber" { - $path = Export-Alias alias.csv - - try - { - Export-Alias alias.csv -NoClobber - } - catch - { - $exportAliasError = $_ - } - - $exportAliasError.FullyQualifiedErrorId | Should Be "NoClobber,Microsoft.PowerShell.Commands.ExportAliasCommand" - } - - AfterEach { - Pop-Location - } - } - - Context "Import-Alias literal path" { - - BeforeAll { - $csvFile = Join-Path $testPath "alias.csv" - $ps1File = Join-Path $testPath "alias.ps1" - - $testCases = @() - $testCases += [TestData]::new("Empty string", "", "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ImportAliasCommand") - $testCases += [TestData]::new("Null", [NullString]::Value, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ImportAliasCommand") - $testCases += [TestData]::new("Non filesystem provider", 'cert:\alias.ps1', "NotSupported,Microsoft.PowerShell.Commands.ImportAliasCommand") - } - - $testCases | % { - - It "for $($_.testName)" { - $test = $_ - - try - { - Import-Alias -LiteralPath $test.testFile -ErrorAction SilentlyContinue - } - catch - { - $exportAliasError = $_ - } - - $exportAliasError.FullyqualifiedErrorId | Should Be $test.expectedError - } - } - - It "can be done from a CSV file" { - - # alias file definition content - $aliasDefinition = @' - "myuh","update-help","","ReadOnly, AllScope" -'@ - - $aliasFile = Join-Path $testPath "alias.csv" - $aliasDefinition | Out-File -LiteralPath $aliasFile - - Import-Alias -LiteralPath $aliasFile - - # Verify that the alias was imported - $definedAlias = Get-Alias myuh - - $definedAlias | Should Not Be $null - $definedAlias.Name | Should Be "myuh" - $definedAlias.Definition | Should Be "update-help" - } - } -} +Describe "Alias tests" -Tags "CI" { + + BeforeAll { + $testPath = Join-Path testdrive:\ ("testAlias\[.test") + New-Item -ItemType Directory -Path $testPath -Force | Out-Null + + class TestData + { + [string] $testName + [string] $testFile + [string] $expectedError + + TestData($name, $file, $error) + { + $this.testName = $name + $this.testFile = $file + $this.expectedError = $error + } + } + } + + Context "Export-Alias literal path" { + BeforeAll { + $csvFile = Join-Path $testPath "alias.csv" + $ps1File = Join-Path $testPath "alias.ps1" + + $testCases = @() + $testCases += [TestData]::new("CSV", $csvFile, [NullString]::Value) + $testCases += [TestData]::new("PS1", $ps1File, [NullString]::Value) + $testCases += [TestData]::new("Empty string", "", "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ExportAliasCommand") + $testCases += [TestData]::new("Null", [NullString]::Value, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportAliasCommand") + $testCases += [TestData]::new("Non filesystem provider", 'cert:\alias.ps1', "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ExportAliasCommand") + } + + $testCases | % { + + It "for $($_.testName)" { + + $test = $_ + try + { + Export-Alias -LiteralPath $test.testFile -ErrorAction SilentlyContinue + } + catch + { + $exportAliasError = $_ + } + + if($test.expectedError -eq $null) + { + Test-Path -LiteralPath $test.testFile | Should Be $true + } + else + { + $exportAliasError.FullyqualifiedErrorId | Should Be $test.expectedError + } + } + + AfterEach { + Remove-Item -LiteralPath $test.testFile -Force -ErrorAction SilentlyContinue + } + } + + It "when file exists with NoClobber" { + Export-Alias -LiteralPath $csvFile + + try + { + Export-Alias -LiteralPath $csvFile -NoClobber + } + catch + { + $exportAliasError = $_ + } + + $exportAliasError.FullyQualifiedErrorId | Should Be "NoClobber,Microsoft.PowerShell.Commands.ExportAliasCommand" + } + } + + Context "Export-All inside a literal path" { + BeforeEach { + Push-Location -LiteralPath $testPath + } + + It "with a CSV file" { + Export-Alias "alias.csv" + Test-Path -LiteralPath (Join-Path $testPath "alias.csv") | Should Be $true + } + + It "with NoClobber" { + $path = Export-Alias alias.csv + + try + { + Export-Alias alias.csv -NoClobber + } + catch + { + $exportAliasError = $_ + } + + $exportAliasError.FullyQualifiedErrorId | Should Be "NoClobber,Microsoft.PowerShell.Commands.ExportAliasCommand" + } + + AfterEach { + Pop-Location + } + } + + Context "Import-Alias literal path" { + + BeforeAll { + $csvFile = Join-Path $testPath "alias.csv" + $ps1File = Join-Path $testPath "alias.ps1" + + $testCases = @() + $testCases += [TestData]::new("Empty string", "", "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ImportAliasCommand") + $testCases += [TestData]::new("Null", [NullString]::Value, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ImportAliasCommand") + $testCases += [TestData]::new("Non filesystem provider", 'cert:\alias.ps1', "NotSupported,Microsoft.PowerShell.Commands.ImportAliasCommand") + } + + $testCases | % { + + It "for $($_.testName)" { + $test = $_ + + try + { + Import-Alias -LiteralPath $test.testFile -ErrorAction SilentlyContinue + } + catch + { + $exportAliasError = $_ + } + + $exportAliasError.FullyqualifiedErrorId | Should Be $test.expectedError + } + } + + It "can be done from a CSV file" { + + # alias file definition content + $aliasDefinition = @' + "myuh","update-help","","ReadOnly, AllScope" +'@ + + $aliasFile = Join-Path $testPath "alias.csv" + $aliasDefinition | Out-File -LiteralPath $aliasFile + + Import-Alias -LiteralPath $aliasFile + + # Verify that the alias was imported + $definedAlias = Get-Alias myuh + + $definedAlias | Should Not Be $null + $definedAlias.Name | Should Be "myuh" + $definedAlias.Definition | Should Be "update-help" + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 index 4ae526145..15477eae9 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 @@ -1,187 +1,187 @@ -Describe "CliXml test" -Tags "CI" { - - BeforeAll { - $testFilePath = Join-Path "testdrive:\" "testCliXml" - $subFilePath = Join-Path $testFilePath ".test" - - if(test-path $testFilePath) - { - Remove-Item $testFilePath -Force -Recurse - } - - # Create the test File and push the location into specified path - New-Item -Path $testFilePath -ItemType Directory | Out-Null - New-Item -Path $subFilePath -ItemType Directory | Out-Null - Push-Location $testFilePath - - class TestData - { - [string] $testName - [object] $inputObject - [string] $expectedError - [string] $testFile - - TestData($name, $file, $inputObj, $error) - { - $this.testName = $name - $this.inputObject = $inputObj - $this.expectedError = $error - $this.testFile = $file - } - } - } - - AfterAll { - Pop-Location - } - - Context "Export-CliXml" { - BeforeAll { - $gpsList = Get-Process powershell - $gps = $gpsList | Select-Object -First 1 - $filePath = Join-Path $subFilePath 'gps.xml' - - $testData = @() - $testData += [TestData]::new("with path as Null", [NullString]::Value, $gps, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportClixmlCommand") - $testData += [TestData]::new("with path as Empty string", "", $gps, "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ExportClixmlCommand") - $testData += [TestData]::new("with path as non filesystem provider", "cert:\", $gps, "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ExportClixmlCommand") - } - - AfterEach { - Remove-Item $filePath -Force -ErrorAction SilentlyContinue - } - - $testData | % { - - It "$($_.testName)" { - $test = $_ - - try - { - Export-Clixml -LiteralPath $test.testFile -InputObject $test.inputObject -Force - } - catch - { - $exportCliXmlError = $_ - } - - $exportCliXmlError.FullyQualifiedErrorId | Should Be $test.expectedError - } - } - - It "can be created with literal path" { - - $filePath = Join-Path $subFilePath 'gps.xml' - Export-Clixml -LiteralPath $filePath -InputObject ($gpsList | Select-Object -First 1) - - $filePath | Should Exist - - $fileContent = Get-Content $filePath - $isExisted = $false - - foreach($item in $fileContent) - { - foreach($gpsItem in $gpsList) - { - $checkId = $gpsItem.Id - if (($null -ne $(Select-String -InputObject $item -SimpleMatch $checkId)) -and ($null -ne $(Select-String -InputObject $item -SimpleMatch "Id"))) - { - $isExisted = $true - break; - } - } - } - - $isExisted | Should Be $true - } - - It "can be created with literal path using pipeline" { - - - $filePath = Join-Path $subFilePath 'gps.xml' - ($gpsList | Select-Object -First 1) | Export-Clixml -LiteralPath $filePath - - $filePath | Should Exist - - $fileContent = Get-Content $filePath - $isExisted = $false - - foreach($item in $fileContent) - { - foreach($gpsItem in $gpsList) - { - $checkId = $gpsItem.Id - if (($null -ne $(Select-String -InputObject $item -SimpleMatch $checkId)) -and ($null -ne $(Select-String -InputObject $item -SimpleMatch "Id"))) - { - $isExisted = $true - break; - } - } - } - - $isExisted | Should Be $true - } - } - - Context "Import-CliXML" { - BeforeAll { - $gpsList = Get-Process powershell - $gps = $gpsList | Select-Object -First 1 - $filePath = Join-Path $subFilePath 'gps.xml' - - $testData = @() - $testData += [TestData]::new("with path as Null", [NullString]::Value, $null, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ImportClixmlCommand") - $testData += [TestData]::new("with path as Empty string", "", $null, "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ImportClixmlCommand") - $testData += [TestData]::new("with path as non filesystem provider", "cert:\", $null, "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ImportClixmlCommand") - } - - $testData | % { - - It "$($_.testName)" { - $test = $_ - - try - { - Import-Clixml -LiteralPath $test.testFile - } - catch - { - $importCliXmlError = $_ - } - - $importCliXmlError.FullyQualifiedErrorId | Should Be $test.expectedError - } - } - - It "can import from a literal path" { - Export-Clixml -LiteralPath $filePath -InputObject $gps - $filePath | Should Exist - - $fileContent = Get-Content $filePath - $fileContent | Should Not Be $null - - $importedProcess = Import-Clixml $filePath - $gps.ProcessName | Should Be $importedProcess.ProcessName - $gps.Id | Should Be $importedProcess.Id - } - - It "can import from a literal path using pipeline" { - $gps | Export-Clixml -LiteralPath $filePath - $filePath | Should Exist - - $fileContent = Get-Content $filePath - $fileContent | Should Not Be $null - - $importedProcess = Import-Clixml $filePath - $gps.ProcessName | Should Be $importedProcess.ProcessName - $gps.Id | Should Be $importedProcess.Id - } - - It "test follow-up for WinBlue: 161470 - Export-CliXml errors in WhatIf scenarios" { - - $testPath = "testdrive:\Bug161470NonExistPath.txt" - Export-Clixml -Path $testPath -InputObject "string" -WhatIf - $testPath | Should Not Exist - } - } -} +Describe "CliXml test" -Tags "CI" { + + BeforeAll { + $testFilePath = Join-Path "testdrive:\" "testCliXml" + $subFilePath = Join-Path $testFilePath ".test" + + if(test-path $testFilePath) + { + Remove-Item $testFilePath -Force -Recurse + } + + # Create the test File and push the location into specified path + New-Item -Path $testFilePath -ItemType Directory | Out-Null + New-Item -Path $subFilePath -ItemType Directory | Out-Null + Push-Location $testFilePath + + class TestData + { + [string] $testName + [object] $inputObject + [string] $expectedError + [string] $testFile + + TestData($name, $file, $inputObj, $error) + { + $this.testName = $name + $this.inputObject = $inputObj + $this.expectedError = $error + $this.testFile = $file + } + } + } + + AfterAll { + Pop-Location + } + + Context "Export-CliXml" { + BeforeAll { + $gpsList = Get-Process powershell + $gps = $gpsList | Select-Object -First 1 + $filePath = Join-Path $subFilePath 'gps.xml' + + $testData = @() + $testData += [TestData]::new("with path as Null", [NullString]::Value, $gps, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportClixmlCommand") + $testData += [TestData]::new("with path as Empty string", "", $gps, "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ExportClixmlCommand") + $testData += [TestData]::new("with path as non filesystem provider", "cert:\", $gps, "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ExportClixmlCommand") + } + + AfterEach { + Remove-Item $filePath -Force -ErrorAction SilentlyContinue + } + + $testData | % { + + It "$($_.testName)" { + $test = $_ + + try + { + Export-Clixml -LiteralPath $test.testFile -InputObject $test.inputObject -Force + } + catch + { + $exportCliXmlError = $_ + } + + $exportCliXmlError.FullyQualifiedErrorId | Should Be $test.expectedError + } + } + + It "can be created with literal path" { + + $filePath = Join-Path $subFilePath 'gps.xml' + Export-Clixml -LiteralPath $filePath -InputObject ($gpsList | Select-Object -First 1) + + $filePath | Should Exist + + $fileContent = Get-Content $filePath + $isExisted = $false + + foreach($item in $fileContent) + { + foreach($gpsItem in $gpsList) + { + $checkId = $gpsItem.Id + if (($null -ne $(Select-String -InputObject $item -SimpleMatch $checkId)) -and ($null -ne $(Select-String -InputObject $item -SimpleMatch "Id"))) + { + $isExisted = $true + break; + } + } + } + + $isExisted | Should Be $true + } + + It "can be created with literal path using pipeline" { + + + $filePath = Join-Path $subFilePath 'gps.xml' + ($gpsList | Select-Object -First 1) | Export-Clixml -LiteralPath $filePath + + $filePath | Should Exist + + $fileContent = Get-Content $filePath + $isExisted = $false + + foreach($item in $fileContent) + { + foreach($gpsItem in $gpsList) + { + $checkId = $gpsItem.Id + if (($null -ne $(Select-String -InputObject $item -SimpleMatch $checkId)) -and ($null -ne $(Select-String -InputObject $item -SimpleMatch "Id"))) + { + $isExisted = $true + break; + } + } + } + + $isExisted | Should Be $true + } + } + + Context "Import-CliXML" { + BeforeAll { + $gpsList = Get-Process powershell + $gps = $gpsList | Select-Object -First 1 + $filePath = Join-Path $subFilePath 'gps.xml' + + $testData = @() + $testData += [TestData]::new("with path as Null", [NullString]::Value, $null, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ImportClixmlCommand") + $testData += [TestData]::new("with path as Empty string", "", $null, "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ImportClixmlCommand") + $testData += [TestData]::new("with path as non filesystem provider", "cert:\", $null, "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ImportClixmlCommand") + } + + $testData | % { + + It "$($_.testName)" { + $test = $_ + + try + { + Import-Clixml -LiteralPath $test.testFile + } + catch + { + $importCliXmlError = $_ + } + + $importCliXmlError.FullyQualifiedErrorId | Should Be $test.expectedError + } + } + + It "can import from a literal path" { + Export-Clixml -LiteralPath $filePath -InputObject $gps + $filePath | Should Exist + + $fileContent = Get-Content $filePath + $fileContent | Should Not Be $null + + $importedProcess = Import-Clixml $filePath + $gps.ProcessName | Should Be $importedProcess.ProcessName + $gps.Id | Should Be $importedProcess.Id + } + + It "can import from a literal path using pipeline" { + $gps | Export-Clixml -LiteralPath $filePath + $filePath | Should Exist + + $fileContent = Get-Content $filePath + $fileContent | Should Not Be $null + + $importedProcess = Import-Clixml $filePath + $gps.ProcessName | Should Be $importedProcess.ProcessName + $gps.Id | Should Be $importedProcess.Id + } + + It "test follow-up for WinBlue: 161470 - Export-CliXml errors in WhatIf scenarios" { + + $testPath = "testdrive:\Bug161470NonExistPath.txt" + Export-Clixml -Path $testPath -InputObject "string" -WhatIf + $testPath | Should Not Exist + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 index 94d554989..6aeb05ad2 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 @@ -1,80 +1,80 @@ -Describe "Trace-Command" -tags "Feature" { - - Context "Listner options" { - BeforeAll { - $logFile = setup -f traceCommandLog.txt -pass - $actualLogFile = setup -f actualTraceCommandLog.txt -pass - } - - AfterEach { - if ( test-path $logfile ) { Remove-Item $logFile } - if ( test-path $actualLogFile ) { Remove-Item $actualLogFile } - } - - It "LogicalOperationStack works" -pending:($IsCore) { - $keyword = "Trace_Command_ListenerOption_LogicalOperationStack_Foo" - $stack = [System.Diagnostics.Trace]::CorrelationManager.LogicalOperationStack - $stack.Push($keyword) - - Trace-Command -Name * -Expression {write-output Foo} -ListenerOption LogicalOperationStack -FilePath $logfile - - $log = Get-Content $logfile | Where-Object {$_ -like "*LogicalOperationStack=$keyword*"} - $log.Count | Should BeGreaterThan 0 - } - - It "Callstack works" -pending:($IsCore) { - Trace-Command -Name * -Expression {write-output Foo} -ListenerOption Callstack -FilePath $logfile - $log = Get-Content $logfile | Where-Object {$_ -like "*Callstack= * System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)*"} - $log.Count | Should BeGreaterThan 0 - } - - It "Datetime works" { - $expectedDate = Trace-Command -Name * -Expression {Get-Date} -ListenerOption DateTime -FilePath $logfile - $log = Get-Content $logfile | Where-Object {$_ -like "*DateTime=*"} - $results = $log | ForEach-Object {[DateTime]::Parse($_.Split("=")[1])} - - ## allow a gap of 6 seconds. All traces should be finished within 6 seconds. - $allowedGap = [timespan](60 * 1000 * 1000) - $results | ForEach-Object { - $actualGap = $_ - $expectedDate; - if ($expectedDate -gt $_) - { - $actualGap = $expectedDate - $_; - } - - $allowedGap | Should BeGreaterThan $actualGap - } - } - - It "None options has no effect" { - Trace-Command -Name * -Expression {write-output Foo} -ListenerOption None -FilePath $actualLogfile - Trace-Command -name * -Expression {write-output Foo} -FilePath $logfile - - Compare-Object (Get-Content $actualLogfile) (Get-Content $logfile) | Should BeNullOrEmpty - } - - It "ThreadID works" { - Trace-Command -Name * -Expression {write-output Foo} -ListenerOption ThreadId -FilePath $logfile - $log = Get-Content $logfile | Where-Object {$_ -like "*ThreadID=*"} - $results = $log | ForEach-Object {$_.Split("=")[1]} - - $results | % { $_ | Should Be ([threading.thread]::CurrentThread.ManagedThreadId) } - } - - It "Timestamp creates logs in ascending order" { - Trace-Command -Name * -Expression {write-output Foo} -ListenerOption Timestamp -FilePath $logfile - $log = Get-Content $logfile | Where-Object {$_ -like "*Timestamp=*"} - $results = $log | ForEach-Object {$_.Split("=")[1]} - $sortedResults = $results | Sort-Object - $sortedResults | Should Be $results - } - - It "ProcessId logs current process Id" { - Trace-Command -Name * -Expression {write-output Foo} -ListenerOption ProcessId -FilePath $logfile - $log = Get-Content $logfile | Where-Object {$_ -like "*ProcessID=*"} - $results = $log | ForEach-Object {$_.Split("=")[1]} - - $results | ForEach-Object { $_ | Should Be $pid } - } - } -} +Describe "Trace-Command" -tags "Feature" { + + Context "Listner options" { + BeforeAll { + $logFile = setup -f traceCommandLog.txt -pass + $actualLogFile = setup -f actualTraceCommandLog.txt -pass + } + + AfterEach { + if ( test-path $logfile ) { Remove-Item $logFile } + if ( test-path $actualLogFile ) { Remove-Item $actualLogFile } + } + + It "LogicalOperationStack works" -pending:($IsCore) { + $keyword = "Trace_Command_ListenerOption_LogicalOperationStack_Foo" + $stack = [System.Diagnostics.Trace]::CorrelationManager.LogicalOperationStack + $stack.Push($keyword) + + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption LogicalOperationStack -FilePath $logfile + + $log = Get-Content $logfile | Where-Object {$_ -like "*LogicalOperationStack=$keyword*"} + $log.Count | Should BeGreaterThan 0 + } + + It "Callstack works" -pending:($IsCore) { + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption Callstack -FilePath $logfile + $log = Get-Content $logfile | Where-Object {$_ -like "*Callstack= * System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)*"} + $log.Count | Should BeGreaterThan 0 + } + + It "Datetime works" { + $expectedDate = Trace-Command -Name * -Expression {Get-Date} -ListenerOption DateTime -FilePath $logfile + $log = Get-Content $logfile | Where-Object {$_ -like "*DateTime=*"} + $results = $log | ForEach-Object {[DateTime]::Parse($_.Split("=")[1])} + + ## allow a gap of 6 seconds. All traces should be finished within 6 seconds. + $allowedGap = [timespan](60 * 1000 * 1000) + $results | ForEach-Object { + $actualGap = $_ - $expectedDate; + if ($expectedDate -gt $_) + { + $actualGap = $expectedDate - $_; + } + + $allowedGap | Should BeGreaterThan $actualGap + } + } + + It "None options has no effect" { + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption None -FilePath $actualLogfile + Trace-Command -name * -Expression {write-output Foo} -FilePath $logfile + + Compare-Object (Get-Content $actualLogfile) (Get-Content $logfile) | Should BeNullOrEmpty + } + + It "ThreadID works" { + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption ThreadId -FilePath $logfile + $log = Get-Content $logfile | Where-Object {$_ -like "*ThreadID=*"} + $results = $log | ForEach-Object {$_.Split("=")[1]} + + $results | % { $_ | Should Be ([threading.thread]::CurrentThread.ManagedThreadId) } + } + + It "Timestamp creates logs in ascending order" { + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption Timestamp -FilePath $logfile + $log = Get-Content $logfile | Where-Object {$_ -like "*Timestamp=*"} + $results = $log | ForEach-Object {$_.Split("=")[1]} + $sortedResults = $results | Sort-Object + $sortedResults | Should Be $results + } + + It "ProcessId logs current process Id" { + Trace-Command -Name * -Expression {write-output Foo} -ListenerOption ProcessId -FilePath $logfile + $log = Get-Content $logfile | Where-Object {$_ -like "*ProcessID=*"} + $results = $log | ForEach-Object {$_.Split("=")[1]} + + $results | ForEach-Object { $_ | Should Be $pid } + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1 index d1f08eeef..14f8fc76d 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/formatdata.tests.ps1 @@ -1,64 +1,64 @@ -Describe "FormatData" -tags "Feature" { - - Context "Export" { - It "can export all types" { - try - { - $expectAllFormat = Get-FormatData -typename * - $expectAllFormat | Export-FormatData -path $TESTDRIVE\allformat.ps1xml -IncludeScriptBlock - - $sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() - $sessionState.Formats.Clear() - $sessionState.Types.Clear() - - $runspace = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace($sessionState) - $runspace.Open() - - $runspace.CreatePipeline("Update-FormatData -AppendPath $TESTDRIVE\allformat.ps1xml").Invoke() - $actualAllFormat = $runspace.CreatePipeline("Get-FormatData -TypeName *").Invoke() - - $expectAllFormat.Count | Should Be $actualAllFormat.Count - Compare-Object $expectAllFormat $actualAllFormat | Should Be $null - $runspace.Close() - } - finally - { - Remove-Item -Path $TESTDRIVE\allformat.ps1xml -Force -ErrorAction SilentlyContinue - } - } - - It "works with literal path" { - $filename = 'TestDrive:\[formats.ps1xml' - Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename - (Test-Path -LiteralPath $filename) | Should Be $true - } - - It "should overwrite the destination file" { - $filename = 'TestDrive:\ExportFormatDataWithForce.ps1xml' - $unexpected = "SHOULD BE OVERWRITTEN" - $unexpected | Out-File -FilePath $filename -Force - $file = Get-Item $filename - $file.IsReadOnly = $true - Get-FormatData -TypeName * | Export-FormatData -Path $filename -Force - - $actual = @(Get-Content $filename)[0] - $actual | Should Not Be $unexpected - } - - It "should not overwrite the destination file with NoClobber" { - $filename = "TestDrive:\ExportFormatDataWithNoClobber.ps1xml" - Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename - - try - { - Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename -NoClobber - } - catch - { - $exportFormatError = $_ - } - - $exportFormatError.FullyQualifiedErrorId | Should Be 'NoClobber,Microsoft.PowerShell.Commands.ExportFormatDataCommand' - } - } -} +Describe "FormatData" -tags "Feature" { + + Context "Export" { + It "can export all types" { + try + { + $expectAllFormat = Get-FormatData -typename * + $expectAllFormat | Export-FormatData -path $TESTDRIVE\allformat.ps1xml -IncludeScriptBlock + + $sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() + $sessionState.Formats.Clear() + $sessionState.Types.Clear() + + $runspace = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace($sessionState) + $runspace.Open() + + $runspace.CreatePipeline("Update-FormatData -AppendPath $TESTDRIVE\allformat.ps1xml").Invoke() + $actualAllFormat = $runspace.CreatePipeline("Get-FormatData -TypeName *").Invoke() + + $expectAllFormat.Count | Should Be $actualAllFormat.Count + Compare-Object $expectAllFormat $actualAllFormat | Should Be $null + $runspace.Close() + } + finally + { + Remove-Item -Path $TESTDRIVE\allformat.ps1xml -Force -ErrorAction SilentlyContinue + } + } + + It "works with literal path" { + $filename = 'TestDrive:\[formats.ps1xml' + Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename + (Test-Path -LiteralPath $filename) | Should Be $true + } + + It "should overwrite the destination file" { + $filename = 'TestDrive:\ExportFormatDataWithForce.ps1xml' + $unexpected = "SHOULD BE OVERWRITTEN" + $unexpected | Out-File -FilePath $filename -Force + $file = Get-Item $filename + $file.IsReadOnly = $true + Get-FormatData -TypeName * | Export-FormatData -Path $filename -Force + + $actual = @(Get-Content $filename)[0] + $actual | Should Not Be $unexpected + } + + It "should not overwrite the destination file with NoClobber" { + $filename = "TestDrive:\ExportFormatDataWithNoClobber.ps1xml" + Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename + + try + { + Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename -NoClobber + } + catch + { + $exportFormatError = $_ + } + + $exportFormatError.FullyQualifiedErrorId | Should Be 'NoClobber,Microsoft.PowerShell.Commands.ExportFormatDataCommand' + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/object.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/object.tests.ps1 index 41d4bf2ea..6a8d1e25c 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/object.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/object.tests.ps1 @@ -1,100 +1,100 @@ -Describe "Object cmdlets" -Tags "CI" { - Context "Group-Object" { - It "AsHashtable returns a hashtable" { - $result = Get-Process | Group-Object -Property ProcessName -AsHashTable - $result["powershell"].Count | Should BeGreaterThan 0 - } - - It "AsString returns a string" { - $processes = Get-Process | Group-Object -Property ProcessName -AsHashTable -AsString - $result = $processes.Keys | ForEach-Object {$_.GetType()} - $result[0].Name | Should Be "String" - } - } - - Context "Tee-Object" { - It "with literal path" { - $path = "TestDrive:\[TeeObjectLiteralPathShouldWorkForSpecialFilename].txt" - Write-Output "Test" | Tee-Object -LiteralPath $path | Tee-Object -Variable TeeObjectLiteralPathShouldWorkForSpecialFilename - $TeeObjectLiteralPathShouldWorkForSpecialFilename | Should Be (Get-Content -LiteralPath $path) - } - } -} - -Describe "Object cmdlets" -Tags "CI" { - Context "Measure-Object" { - BeforeAll { - ## Powershell language prefers , as an array seperator without "". - ## If a number has comma in them it considers it to be the 1000 seperator like "1,000". - ## In de-DE language the comma is used as decimal point, but powershell still uses it as a 1000 seperator. - ## In case the number has a comma, it is ignored. So, "99,1" becomes 991. - ## To work around that behavior, we use ToString() on the expected answer and . for decimal in the input. - - $firstValue = "9995788.71" - $expectedFirstValue = $null - $null = [System.Management.Automation.LanguagePrimitives]::TryConvertTo($firstValue, [double], [cultureinfo]::InvariantCulture, [ref] $expectedFirstValue) - $firstObject = new-object psobject - $firstObject | Add-Member -NotePropertyName Header -NotePropertyValue $firstValue - - $secondValue = "15847577.7" - $expectedSecondValue = $null - $null = [System.Management.Automation.LanguagePrimitives]::TryConvertTo($secondValue, [double], [cultureinfo]::InvariantCulture, [ref] $expectedSecondValue) - $secondObject = new-object psobject - $secondObject | Add-Member -NotePropertyName Header -NotePropertyValue $secondValue - - $testCases = @( - @{ data = @("abc","ABC","Def"); min = "abc"; max = "Def"}, - @{ data = @([datetime]::Today, [datetime]::Today.AddDays(-1)); min = ([datetime]::Today.AddDays(-1)).ToString() ; max = [datetime]::Today.ToString() } - @{ data = @(1,2,3,"ABC"); min = 1; max = "ABC"}, - @{ data = @(4,2,3,"ABC",1); min = 1; max = "ABC"}, - @{ data = @(4,2,3,"ABC",1,"DEF"); min = 1; max = "DEF"}, - @{ data = @("111 Test","19"); min = "111 Test"; max = "19"}, - @{ data = @("19", "111 Test"); min = "111 Test"; max = "19"}, - @{ data = @("111 Test",19); min = "111 Test"; max = 19}, - @{ data = @(19, "111 Test"); min = "111 Test"; max = 19}, - @{ data = @(100,2,3, "A", 1); min = 1; max = "A"}, - @{ data = @(4,2,3, "ABC", 1, "DEF"); min = 1; max = "DEF"}, - @{ data = @("abc",[Datetime]::Today,"def"); min = [Datetime]::Today.ToString(); max = "def"} - ) - } - - It "can compare string representation for minimum" { - $minResult = $firstObject, $secondObject | Measure-Object Header -Minimum - $minResult.Minimum.ToString() | Should Be $expectedFirstValue.ToString() - } - - It "can compare string representation for maximum" { - $maxResult = $firstObject, $secondObject | Measure-Object Header -Maximum - $maxResult.Maximum.ToString() | Should Be $expectedSecondValue.ToString() - } - - It 'correctly find minimum of ()' -TestCases $testCases { - param($data, $min, $max) - - $output = $data | Measure-Object -Minimum - $output.Minimum.ToString() | Should Be $min - } - - It 'correctly find maximum of ()' -TestCases $testCases { - param($data, $min, $max) - - $output = $data | Measure-Object -Maximum - $output.Maximum.ToString() | Should Be $max - } - - It 'returns a GenericMeasureInfoObject' { - $gmi = 1,2,3 | measure-object -max -min - $gmi.GetType().FullName | Should Be 'Microsoft.PowerShell.Commands.GenericMeasureInfo' - } - - It 'should return correct error for non-numeric input' { - $gmi = "abc",[Datetime]::Now | measure -sum -max -ev err -ea silentlycontinue - $err | % { $_.FullyQualifiedErrorId | Should Be 'NonNumericInputObject,Microsoft.PowerShell.Commands.MeasureObjectCommand' } - } - - It 'should have the correct count' { - $gmi = "abc",[Datetime]::Now | measure -sum -max -ev err -ea silentlycontinue - $gmi.Count | Should Be 2 - } - } -} +Describe "Object cmdlets" -Tags "CI" { + Context "Group-Object" { + It "AsHashtable returns a hashtable" { + $result = Get-Process | Group-Object -Property ProcessName -AsHashTable + $result["powershell"].Count | Should BeGreaterThan 0 + } + + It "AsString returns a string" { + $processes = Get-Process | Group-Object -Property ProcessName -AsHashTable -AsString + $result = $processes.Keys | ForEach-Object {$_.GetType()} + $result[0].Name | Should Be "String" + } + } + + Context "Tee-Object" { + It "with literal path" { + $path = "TestDrive:\[TeeObjectLiteralPathShouldWorkForSpecialFilename].txt" + Write-Output "Test" | Tee-Object -LiteralPath $path | Tee-Object -Variable TeeObjectLiteralPathShouldWorkForSpecialFilename + $TeeObjectLiteralPathShouldWorkForSpecialFilename | Should Be (Get-Content -LiteralPath $path) + } + } +} + +Describe "Object cmdlets" -Tags "CI" { + Context "Measure-Object" { + BeforeAll { + ## Powershell language prefers , as an array seperator without "". + ## If a number has comma in them it considers it to be the 1000 seperator like "1,000". + ## In de-DE language the comma is used as decimal point, but powershell still uses it as a 1000 seperator. + ## In case the number has a comma, it is ignored. So, "99,1" becomes 991. + ## To work around that behavior, we use ToString() on the expected answer and . for decimal in the input. + + $firstValue = "9995788.71" + $expectedFirstValue = $null + $null = [System.Management.Automation.LanguagePrimitives]::TryConvertTo($firstValue, [double], [cultureinfo]::InvariantCulture, [ref] $expectedFirstValue) + $firstObject = new-object psobject + $firstObject | Add-Member -NotePropertyName Header -NotePropertyValue $firstValue + + $secondValue = "15847577.7" + $expectedSecondValue = $null + $null = [System.Management.Automation.LanguagePrimitives]::TryConvertTo($secondValue, [double], [cultureinfo]::InvariantCulture, [ref] $expectedSecondValue) + $secondObject = new-object psobject + $secondObject | Add-Member -NotePropertyName Header -NotePropertyValue $secondValue + + $testCases = @( + @{ data = @("abc","ABC","Def"); min = "abc"; max = "Def"}, + @{ data = @([datetime]::Today, [datetime]::Today.AddDays(-1)); min = ([datetime]::Today.AddDays(-1)).ToString() ; max = [datetime]::Today.ToString() } + @{ data = @(1,2,3,"ABC"); min = 1; max = "ABC"}, + @{ data = @(4,2,3,"ABC",1); min = 1; max = "ABC"}, + @{ data = @(4,2,3,"ABC",1,"DEF"); min = 1; max = "DEF"}, + @{ data = @("111 Test","19"); min = "111 Test"; max = "19"}, + @{ data = @("19", "111 Test"); min = "111 Test"; max = "19"}, + @{ data = @("111 Test",19); min = "111 Test"; max = 19}, + @{ data = @(19, "111 Test"); min = "111 Test"; max = 19}, + @{ data = @(100,2,3, "A", 1); min = 1; max = "A"}, + @{ data = @(4,2,3, "ABC", 1, "DEF"); min = 1; max = "DEF"}, + @{ data = @("abc",[Datetime]::Today,"def"); min = [Datetime]::Today.ToString(); max = "def"} + ) + } + + It "can compare string representation for minimum" { + $minResult = $firstObject, $secondObject | Measure-Object Header -Minimum + $minResult.Minimum.ToString() | Should Be $expectedFirstValue.ToString() + } + + It "can compare string representation for maximum" { + $maxResult = $firstObject, $secondObject | Measure-Object Header -Maximum + $maxResult.Maximum.ToString() | Should Be $expectedSecondValue.ToString() + } + + It 'correctly find minimum of ()' -TestCases $testCases { + param($data, $min, $max) + + $output = $data | Measure-Object -Minimum + $output.Minimum.ToString() | Should Be $min + } + + It 'correctly find maximum of ()' -TestCases $testCases { + param($data, $min, $max) + + $output = $data | Measure-Object -Maximum + $output.Maximum.ToString() | Should Be $max + } + + It 'returns a GenericMeasureInfoObject' { + $gmi = 1,2,3 | measure-object -max -min + $gmi.GetType().FullName | Should Be 'Microsoft.PowerShell.Commands.GenericMeasureInfo' + } + + It 'should return correct error for non-numeric input' { + $gmi = "abc",[Datetime]::Now | measure -sum -max -ev err -ea silentlycontinue + $err | % { $_.FullyQualifiedErrorId | Should Be 'NonNumericInputObject,Microsoft.PowerShell.Commands.MeasureObjectCommand' } + } + + It 'should have the correct count' { + $gmi = "abc",[Datetime]::Now | measure -sum -max -ev err -ea silentlycontinue + $gmi.Count | Should Be 2 + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 index bdcfa965d..5f7c0e776 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 @@ -1,63 +1,63 @@ -Describe "String cmdlets" -Tags "CI" { - Context "Select-String" { - BeforeAll { - $sep = [io.path]::DirectorySeparatorChar - $fileName = New-Item 'TestDrive:\selectStr[ingLi]teralPath.txt' - "abc" | Out-File -LiteralPath $fileName.fullname - "bcd" | Out-File -LiteralPath $fileName.fullname -Append - "cde" | Out-File -LiteralPath $fileName.fullname -Append - - $fileNameWithDots = $fileName.FullName.Replace("\", "\.\") - - $tempFile = New-TemporaryFile - "abc" | Out-File -LiteralPath $tempFile.fullname - "bcd" | Out-File -LiteralPath $tempFile.fullname -Append - "cde" | Out-File -LiteralPath $tempFile.fullname -Append - $driveLetter = $tempFile.PSDrive.Name - $fileNameAsNetworkPath = "\\localhost\$driveLetter`$" + $tempFile.FullName.SubString(2) - - Push-Location "$fileName\.." - } - - AfterAll { - Remove-Item $tempFile -Force -ErrorAction SilentlyContinue - Pop-Location - } - - It "LiteralPath with relative path" { - (select-string -LiteralPath (Get-Item -LiteralPath $fileName).Name "b").count | Should Be 2 - } - - It "LiteralPath with absolute path" { - (select-string -LiteralPath $fileName "b").count | Should Be 2 - } - - It "LiteralPath with dots in path" { - (select-string -LiteralPath $fileNameWithDots "b").count | Should Be 2 - } - - It "Network path" -skip:($IsCore) { - (select-string -LiteralPath $fileNameAsNetworkPath "b").count | Should Be 2 - } - - It "throws error for non filesystem providers" { - $aaa = "aaaaaaaaaa" - select-string -literalPath variable:\aaa "a" -ErrorAction SilentlyContinue -ErrorVariable selectStringError - $selectStringError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectStringCommand' - } - - It "throws parameter binding exception for invalid context" { - { select-string It $PSScriptRoot -Context -1,-1 } | Should Throw Context - } - - It "match object supports RelativePath method" { - $file = "Modules${sep}Microsoft.PowerShell.Utility${sep}Microsoft.PowerShell.Utility.psd1" - - $match = Select-String CmdletsToExport $pshome/$file - - $match.RelativePath($pshome) | Should Be $file - $match.RelativePath($pshome.ToLower()) | Should Be $file - $match.RelativePath($pshome.ToUpper()) | Should Be $file - } - } -} +Describe "String cmdlets" -Tags "CI" { + Context "Select-String" { + BeforeAll { + $sep = [io.path]::DirectorySeparatorChar + $fileName = New-Item 'TestDrive:\selectStr[ingLi]teralPath.txt' + "abc" | Out-File -LiteralPath $fileName.fullname + "bcd" | Out-File -LiteralPath $fileName.fullname -Append + "cde" | Out-File -LiteralPath $fileName.fullname -Append + + $fileNameWithDots = $fileName.FullName.Replace("\", "\.\") + + $tempFile = New-TemporaryFile + "abc" | Out-File -LiteralPath $tempFile.fullname + "bcd" | Out-File -LiteralPath $tempFile.fullname -Append + "cde" | Out-File -LiteralPath $tempFile.fullname -Append + $driveLetter = $tempFile.PSDrive.Name + $fileNameAsNetworkPath = "\\localhost\$driveLetter`$" + $tempFile.FullName.SubString(2) + + Push-Location "$fileName\.." + } + + AfterAll { + Remove-Item $tempFile -Force -ErrorAction SilentlyContinue + Pop-Location + } + + It "LiteralPath with relative path" { + (select-string -LiteralPath (Get-Item -LiteralPath $fileName).Name "b").count | Should Be 2 + } + + It "LiteralPath with absolute path" { + (select-string -LiteralPath $fileName "b").count | Should Be 2 + } + + It "LiteralPath with dots in path" { + (select-string -LiteralPath $fileNameWithDots "b").count | Should Be 2 + } + + It "Network path" -skip:($IsCore) { + (select-string -LiteralPath $fileNameAsNetworkPath "b").count | Should Be 2 + } + + It "throws error for non filesystem providers" { + $aaa = "aaaaaaaaaa" + select-string -literalPath variable:\aaa "a" -ErrorAction SilentlyContinue -ErrorVariable selectStringError + $selectStringError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectStringCommand' + } + + It "throws parameter binding exception for invalid context" { + { select-string It $PSScriptRoot -Context -1,-1 } | Should Throw Context + } + + It "match object supports RelativePath method" { + $file = "Modules${sep}Microsoft.PowerShell.Utility${sep}Microsoft.PowerShell.Utility.psd1" + + $match = Select-String CmdletsToExport $pshome/$file + + $match.RelativePath($pshome) | Should Be $file + $match.RelativePath($pshome.ToLower()) | Should Be $file + $match.RelativePath($pshome.ToUpper()) | Should Be $file + } + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/typedata.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/typedata.tests.ps1 index 5f88d447af4675db30638b6ea701ecea02873503..cf4c4233714c48880bfe43d6db0e75e32889ac8e 100644 GIT binary patch literal 5169 zcmdT|+fw635PkPobO~1h0Sm|@@sc&Slq&@xYqELR?86|nu@*_A%#1K%moLjhJ}JMD z?vY36VzM~JZYr*F*|J)FJKd*y{MR3U9-|IabcNtuqBh6E2ndoeMx#9#T#9QA-qF~D zk3FE*kxUKV8Ss8UGq@}=WO;X!1;%u5QfPyTKT=8*^?Q7Oqy8Y&B{zN6cPrPtp#L^fKke1f|5RSZ7#D#aWjdkP{5Fh(Ve zRFtYRKc#E!Fl{DQF~@3}nacE$!VpsviTIy2orzRjV?v_-C^s?@CX%UtF?oEx3Z)g* zhyuzCBzbJ2EJiRCWhb(}{S{s{QrSRh+g&a74iL<{ql677UA~DD%@Uta<^vJTEd?@0xy^$8pU7N3$@q2A4AgMZFGk z3TB3ykftjQq2$X*!Ca~vh*A)#q#qQhJk^;9NKS&dl~D)@YEA71dB%@GkSj$6R|#6n z6<7R{g~H%cx;R7v3P*9=>YqMyQfBruO%T4jkaJX%8OHJZ{e7xq(zfx4T`hg3x)Tx1 z+WIn0z$b}FL;4bY7&?jQk`i3L@B8{QZ+N9sX?{GY0_~V=}hXndscfroHjNU zOpaMbp~%PpWI_=e(zkXI*ruSw^vU2T3@0{M8?U`yE7Qc^j#A$;YWC7;KZ^n-wVWFN zF}?m#l<<3;Y9rDB7qY!&RmU28-s??&oZiZtPQ*+TpKDvIg7f2EHZb?p!nl7*rQ8_{ zt9b9UmmRmjv8v8Dn8@2NSDkEpf`%Gpa0+3bB*mU@Db&yO-dz&Iz;|&=tePBNh zh8*%iQ547g%y7qE4$m;TLPatq=8ij`kS5qlxx-inHwWuZ+xl>)b!)iOR=87{+F`d2 zhW0}rcvZP}Bl~uR$nNj&SBR`F-Ex23-G7rM zQj6`jSLK>>Nsk=U6X(*L@B@037IPX3=)qRGqr4$fmB}L?b6qr<$!qmkjhAf4vpw%A zB54yd(*sjN@pCTXXc}Q?`Fb2S=B-`P^l_1jBnnFNCwIKw&@!~WoIKokD5bgRdAVIo z4G*fiuT{s|+DG6yP!3X<$~cyDo{L1~SKM9nfqhG4jGqbZ6X@j^miAZY-x#Up8ETAE`Ijlac%Tu3y`uUT-M4d32_=1 l>$d+R7JS{9t;;%aS@dgb5A}5(yw4U_OZj6*Lx)AuZ_goAi)8ur4|Fx5NL^+D)_ zzRpi|_lnMJ=&q;XP`?ZwZa4}J(k1MM{nf9m}xyp&YO z(nUwVZpZUgv!uH4-S}}e&UGv;j5Oa^lA+0wP(Uwz9f$FK7`~p$SSCJ(PaNxbq%(MJPv3?*`#{!Fwtg8l&8Y3nuo`KFOe^6B ztTl@0W%_P@-3Gn2ZIZa&vo^Jw$Gjqtr9;IGo>^C;bhbT^h3 z@kjjgRQJ2pdQ2$OqFY5O-;;1X{Ic|z@*;Z9dRP-8rqS*2rM}tkjffS$a+Ee@8$>fK z$nU%wuF5*=B&+wza{1XqnFcn6A34S%;7_`1stCIn)!O5_qTM^Pi?JH%$C9{PE1`LU zOXA07|CqPM)SigN^?Iw0W!1CR$vKSP*)NrIUcN=SR<+v$;Xu|Sc9D5AS;`B2f)8i7 zMsDXCxvQh=ezm7jSvZOI_)6c%W<>g-&e(XagTqi`N4i1=U^H_)4R3Vp#SBY)o9M+1 zhq^|_^i|*`$C`y5V!?|urdGVjMt;;>9j%5G=iww|ee<=hqHbTWCT!OvfpIJ%=MAlk z#)x@O6lIR2DPj!Vf;`xlr`*uX;dY#a1@vI#%##~45k7-~Eog-^O(*m2v)=(}Xh zisXf3F+0)ZRV&OrGhQ@br#o@{i^m+h;%f66*bH}P_Lk#ORf#MQgW~R+GRR`IeJBJ5 zLgI~%xfL~6fN322x1+6V;gMvR&T`R)@FDvhOS*wr;D~ z&RPjK&v@k|+)94&-7&wVnR)Gn=4 z=rPea5B*A8iHe1F_7s^|<-U$n@lIc3B5pC%y(f`p!%bQBs@{2z@L}X3)G~t##_dt1 zj%%%iR2PfcuAF7%jKC$NmOU?rF}6!pjf9Kr+u4S*iqr6eatb}Eo>*H?V>$^}-`B6| zDl^ypL|Q+Uc3BS|n92_VFgrM%^`)*UuD554U_n>QYmszr$KH7a*)_i#e9O3ab!=G; ztE$uKA6i|P*1TD)`Z!O;<`t>&`e$ePkjf4wPd&>$aCvr)UcJJ#%Gc{+>XFyNfcwxB zT`f4Y`HTAsGg3V<6ZL}C(eP*_ER)hJ4yy)Ij|68buxqXS&MeAiNi#NGn&xU^N4V2N zLkAC}8TL&V>Okl4{5?t2i>&Zx-O+|cEyF9U=Cw{(wY^_2)pNBqIRci6Qv|Hz$2Z<2#>1O_!ea> z^QvaF)A*EP{yy-n^Tl-C@|^Qu^*_4DbO4B}bPTQ6==|hFSBcu3_X@SsDl)pIT~2TF z-7Pn^d3GswcYXCduC33iT2o`0<8&eKA? zBIi5SC(Yvd6R`!Jf92UIk8ACo^<50rgBiomBY3fPC1<4_5Fe4vs(^0E)4cf+`P}nN zHm}`_9SYWbES>Ztcgxh}xvr@3{u%pn{Wr}TplVNjum(pxw;Io27x(0J)r;n;kIQ>g z&9ub>&&1Dpc8w=nr9qe7tBLeUDD?xJbKH_s*7Rqyg?X6udXtG(G%j=^wZ}PO6Tq dJD>yeRv46bV6XcDtJFn(sA{{XUbAG`nn diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 index 119d30a01..7c402aea6 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 @@ -1,68 +1,68 @@ -Describe "XML cmdlets" -Tags "Feature" { - Context "Select-XML" { - BeforeAll { - $fileName = New-Item -Path 'TestDrive:\testSelectXml.xml' - Push-Location "$fileName\.." - "" | out-file -LiteralPath $fileName - " " | out-file -LiteralPath $fileName -Append - "" | out-file -LiteralPath $fileName -Append - - $fileNameWithDots = $fileName.FullName.Replace("\", "\.\") - - $driveLetter = [string]($fileName.FullName)[0] - $fileNameAsNetworkPath = "\\localhost\$driveLetter`$" + $fileName.FullName.SubString(2) - - class TestData - { - [string] $testName - [hashtable] $parameters - - TestData($name, $parameters) - { - $this.testName = $name - $this.parameters = $parameters - } - } - - $testcases = @() - $testcases += [TestData]::new('literalpath with relative paths', @{LiteralPath = $fileName.Name; XPath = 'Root'}) - $testcases += [TestData]::new('literalpath with absolute paths', @{LiteralPath = $fileName.FullName; XPath = 'Root'}) - $testcases += [TestData]::new('literalpath with path with dots', @{LiteralPath = $fileNameWithDots; XPath = 'Root'}) - if ( ! $IsCore ) { - $testcases += [TestData]::new('literalpath with network path', @{LiteralPath = $fileNameAsNetworkPath; XPath = 'Root'}) - } - $testcases += [TestData]::new('path with relative paths', @{Path = $fileName.Name; XPath = 'Root'}) - $testcases += [TestData]::new('path with absolute paths', @{Path = $fileName.FullName; XPath = 'Root'}) - $testcases += [TestData]::new('path with path with dots', @{Path = $fileNameWithDots; XPath = 'Root'}) - if ( ! $IsCore ) { - $testcases += [TestData]::new('path with network path', @{Path = $fileNameAsNetworkPath; XPath = 'Root'}) - } - } - - AfterAll { - Remove-Item -LiteralPath $fileName -Force -ErrorAction SilentlyContinue - Pop-Location - } - - $testcases | % { - - $params = $_.parameters - - It $_.testName { - @(Select-XML @params).Count | Should Be 1 - } - } - - It "literalpath with non filesystem path" { - $__data = "abcdefg" - Select-XML -literalPath variable:__data "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue - $selectXmlError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand' - } - - It "path with non filesystem path" { - $__data = "abcdefg" - Select-XML -Path variable:\__data "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue - $selectXmlError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand' - } - } -} +Describe "XML cmdlets" -Tags "Feature" { + Context "Select-XML" { + BeforeAll { + $fileName = New-Item -Path 'TestDrive:\testSelectXml.xml' + Push-Location "$fileName\.." + "" | out-file -LiteralPath $fileName + " " | out-file -LiteralPath $fileName -Append + "" | out-file -LiteralPath $fileName -Append + + $fileNameWithDots = $fileName.FullName.Replace("\", "\.\") + + $driveLetter = [string]($fileName.FullName)[0] + $fileNameAsNetworkPath = "\\localhost\$driveLetter`$" + $fileName.FullName.SubString(2) + + class TestData + { + [string] $testName + [hashtable] $parameters + + TestData($name, $parameters) + { + $this.testName = $name + $this.parameters = $parameters + } + } + + $testcases = @() + $testcases += [TestData]::new('literalpath with relative paths', @{LiteralPath = $fileName.Name; XPath = 'Root'}) + $testcases += [TestData]::new('literalpath with absolute paths', @{LiteralPath = $fileName.FullName; XPath = 'Root'}) + $testcases += [TestData]::new('literalpath with path with dots', @{LiteralPath = $fileNameWithDots; XPath = 'Root'}) + if ( ! $IsCore ) { + $testcases += [TestData]::new('literalpath with network path', @{LiteralPath = $fileNameAsNetworkPath; XPath = 'Root'}) + } + $testcases += [TestData]::new('path with relative paths', @{Path = $fileName.Name; XPath = 'Root'}) + $testcases += [TestData]::new('path with absolute paths', @{Path = $fileName.FullName; XPath = 'Root'}) + $testcases += [TestData]::new('path with path with dots', @{Path = $fileNameWithDots; XPath = 'Root'}) + if ( ! $IsCore ) { + $testcases += [TestData]::new('path with network path', @{Path = $fileNameAsNetworkPath; XPath = 'Root'}) + } + } + + AfterAll { + Remove-Item -LiteralPath $fileName -Force -ErrorAction SilentlyContinue + Pop-Location + } + + $testcases | % { + + $params = $_.parameters + + It $_.testName { + @(Select-XML @params).Count | Should Be 1 + } + } + + It "literalpath with non filesystem path" { + $__data = "abcdefg" + Select-XML -literalPath variable:__data "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue + $selectXmlError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand' + } + + It "path with non filesystem path" { + $__data = "abcdefg" + Select-XML -Path variable:\__data "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue + $selectXmlError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand' + } + } +} From 0a18a46281ec85672c172f0f0907679d347f9af3 Mon Sep 17 00:00:00 2001 From: James Truher Date: Mon, 25 Jul 2016 12:19:16 -0700 Subject: [PATCH 20/25] Update json tests to be more cross-plat and handle multiple invocations only create the enumtest type if it doesn't exist don't try to compare line endings on json tests which contain arrays, formatting of the output need not be validated --- .../Pester.Commands.Cmdlets.Json.Tests.ps1 | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 index 74c1c9312..6fea81ea0 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 @@ -69,19 +69,25 @@ Describe "Json Tests" -Tags "Feature" { It "Convertto-Json should handle Enum based on Int64" { # Test follow-up for bug Win8: 378368 Convertto-Json problems with Enum based on Int64. - enum TestEnum : ulong { One = 1, Two = 2 } - enum TestEnum1 : long { One = 1, Two = 2 } - enum TestEnum2 : int { One = 1, Two = 2 } + if ( ("JsonEnumTest" -as "Type") -eq $null ) { + $enum1 = "TestEnum" + (get-random) + $enum2 = "TestEnum" + (get-random) + $enum3 = "TestEnum" + (get-random) - class Test { - [TestEnum] $TestEnum = [TestEnum]::One - [TestEnum1] $TestEnum1 = [TestEnum1]::Two - [TestEnum2] $TestEnum2 = [TestEnum2]::One + $jsontype = add-type -pass -TypeDef " + public enum $enum1 : ulong { One = 1, Two = 2 }; + public enum $enum2 : long { One = 1, Two = 2 }; + public enum $enum3 : int { One = 1, Two = 2 }; + public class JsonEnumTest { + public $enum1 TestEnum1 = ${enum1}.One; + public $enum2 TestEnum2 = ${enum2}.Two; + public $enum3 TestEnum3 = ${enum3}.One; + }" } - $op = [Test]::New() | convertto-json | convertfrom-json - $op.TestEnum | Should Be "One" - $op.TestEnum1 | Should Be "Two" - $op.TestEnum2 | Should Be 1 + $op = [JsonEnumTest]::New() | convertto-json | convertfrom-json + $op.TestEnum1 | Should Be "One" + $op.TestEnum2 | Should Be "Two" + $op.TestEnum3 | Should Be 1 } It "Test followup for Windows 8 bug 121627" { @@ -1321,7 +1327,9 @@ Describe "Validate Json serialization" -Tags "CI" { $a = 1..5 $b = 6..10 - $actual = [ordered]@{'a'=$a;'b'=$b} | ConvertTo-Json + # remove whitespace (and newline/cr) which reduces the complexity of a + # cross-plat test + $actual = ([ordered]@{'a'=$a;'b'=$b} | ConvertTo-Json) -replace "\s" $expected = @' { "a": [ @@ -1340,7 +1348,8 @@ Describe "Validate Json serialization" -Tags "CI" { ] } '@ - $actual | Should Be $expected + $expectedNoWhiteSpace = $expected -replace "\s" + $actual | Should Be $expectedNoWhiteSpace } } } From fb2770392d1d1155a6b8b85efd801f3a951c7088 Mon Sep 17 00:00:00 2001 From: Sergei Vorobev Date: Tue, 2 Aug 2016 12:39:30 -0700 Subject: [PATCH 21/25] Remove author tag from all project.json files --- src/Microsoft.PackageManagement.ArchiverProviders/project.json | 1 - src/Microsoft.PackageManagement.CoreProviders/project.json | 1 - .../project.json | 1 - src/Microsoft.PackageManagement.MsiProvider/project.json | 1 - src/Microsoft.PackageManagement.MsuProvider/project.json | 1 - src/Microsoft.PackageManagement.NuGetProvider/project.json | 1 - .../project.json | 1 - src/Microsoft.PackageManagement/project.json | 1 - src/Microsoft.PowerShell.PackageManagement/project.json | 1 - src/Microsoft.PowerShell.Workflow.ServiceCore/project.json | 1 - 10 files changed, 10 deletions(-) diff --git a/src/Microsoft.PackageManagement.ArchiverProviders/project.json b/src/Microsoft.PackageManagement.ArchiverProviders/project.json index 5111eb3de..fa6fe42ae 100644 --- a/src/Microsoft.PackageManagement.ArchiverProviders/project.json +++ b/src/Microsoft.PackageManagement.ArchiverProviders/project.json @@ -1,7 +1,6 @@ { "name": "Microsoft.PackageManagement.ArchiverProviders", "version": "1.0.0-*", - "authors": ["quoct"], "buildOptions": { "warningsAsErrors": true diff --git a/src/Microsoft.PackageManagement.CoreProviders/project.json b/src/Microsoft.PackageManagement.CoreProviders/project.json index d456919d2..db190187a 100644 --- a/src/Microsoft.PackageManagement.CoreProviders/project.json +++ b/src/Microsoft.PackageManagement.CoreProviders/project.json @@ -1,7 +1,6 @@ { "name": "Microsoft.PackageManagement.CoreProviders", "version": "1.0.0-*", - "authors": ["quoct"], "buildOptions": { "warningsAsErrors": true diff --git a/src/Microsoft.PackageManagement.MetaProvider.PowerShell/project.json b/src/Microsoft.PackageManagement.MetaProvider.PowerShell/project.json index 59bff5d34..854a72ffc 100644 --- a/src/Microsoft.PackageManagement.MetaProvider.PowerShell/project.json +++ b/src/Microsoft.PackageManagement.MetaProvider.PowerShell/project.json @@ -1,7 +1,6 @@ { "name": "Microsoft.PackageManagement.MetaProvider.PowerShell", "version": "1.0.0-*", - "authors": ["quoct"], "buildOptions": { "warningsAsErrors": true diff --git a/src/Microsoft.PackageManagement.MsiProvider/project.json b/src/Microsoft.PackageManagement.MsiProvider/project.json index 19a20a4ba..fd5319bb0 100644 --- a/src/Microsoft.PackageManagement.MsiProvider/project.json +++ b/src/Microsoft.PackageManagement.MsiProvider/project.json @@ -1,7 +1,6 @@ { "name": "Microsoft.PackageManagement.MsiProvider", "version": "1.0.0-*", - "authors": ["quoct"], "buildOptions": { "warningsAsErrors": true diff --git a/src/Microsoft.PackageManagement.MsuProvider/project.json b/src/Microsoft.PackageManagement.MsuProvider/project.json index 6a28ff49f..a87fb5303 100644 --- a/src/Microsoft.PackageManagement.MsuProvider/project.json +++ b/src/Microsoft.PackageManagement.MsuProvider/project.json @@ -1,7 +1,6 @@ { "name": "Microsoft.PackageManagement.MsuProvider", "version": "1.0.0-*", - "authors": ["quoct"], "buildOptions": { "warningsAsErrors": true diff --git a/src/Microsoft.PackageManagement.NuGetProvider/project.json b/src/Microsoft.PackageManagement.NuGetProvider/project.json index 691c28366..38ed12469 100644 --- a/src/Microsoft.PackageManagement.NuGetProvider/project.json +++ b/src/Microsoft.PackageManagement.NuGetProvider/project.json @@ -1,7 +1,6 @@ { "name": "Microsoft.PackageManagement.NuGetProvider", "version": "1.0.0-*", - "authors": ["quoct"], "buildOptions": { "warningsAsErrors": true diff --git a/src/Microsoft.PackageManagement.PackageSourceListProvider/project.json b/src/Microsoft.PackageManagement.PackageSourceListProvider/project.json index 1e9f81714..405f709ff 100644 --- a/src/Microsoft.PackageManagement.PackageSourceListProvider/project.json +++ b/src/Microsoft.PackageManagement.PackageSourceListProvider/project.json @@ -1,7 +1,6 @@ { "name": "Microsoft.PackageManagement.PackageSourceListProvider", "version": "1.0.0-*", - "authors": [ "quoct" ], "buildOptions": { "warningsAsErrors": true diff --git a/src/Microsoft.PackageManagement/project.json b/src/Microsoft.PackageManagement/project.json index cf7c2e1d4..56b0f2e4e 100644 --- a/src/Microsoft.PackageManagement/project.json +++ b/src/Microsoft.PackageManagement/project.json @@ -1,7 +1,6 @@ { "name": "Microsoft.PackageManagement", "version": "1.0.0-*", - "authors": [ "quoct" ], "buildOptions": { "warningsAsErrors": true diff --git a/src/Microsoft.PowerShell.PackageManagement/project.json b/src/Microsoft.PowerShell.PackageManagement/project.json index 818dd6d1e..fde8c2f7a 100644 --- a/src/Microsoft.PowerShell.PackageManagement/project.json +++ b/src/Microsoft.PowerShell.PackageManagement/project.json @@ -1,7 +1,6 @@ { "name": "Microsoft.PowerShell.PackageManagement", "version": "1.0.0-*", - "authors": ["quoct"], "buildOptions": { "warningsAsErrors": true diff --git a/src/Microsoft.PowerShell.Workflow.ServiceCore/project.json b/src/Microsoft.PowerShell.Workflow.ServiceCore/project.json index e2fb9c9d6..cd1817990 100644 --- a/src/Microsoft.PowerShell.Workflow.ServiceCore/project.json +++ b/src/Microsoft.PowerShell.Workflow.ServiceCore/project.json @@ -1,7 +1,6 @@ { "name": "Microsoft.PowerShell.Workflow.ServiceCore", "version": "1.0.0-*", - "authors": [ "OPS" ], "buildOptions": { "nowarn": [ "CS1570" ], From 6a07b71ba6c337bf2cfe0bd6d24654d103e34168 Mon Sep 17 00:00:00 2001 From: James Truher Date: Tue, 2 Aug 2016 12:50:24 -0700 Subject: [PATCH 22/25] update tests to include $IsCoreCLR rather than $IsCore also fix archive test to be sure it gets the proper archive module (not the one that's somewhere in the filesystem) --- .../Pester.Commands.Cmdlets.Archive.Tests.ps1 | 29 +++++++++++++------ .../Copy.Item.Tests.ps1 | 2 +- .../FormatHex.Tests.ps1 | 4 +-- .../ImportExportCSV.Delimiter.Tests.ps1 | 4 +-- .../Pester.Commands.Cmdlets.Json.Tests.ps1 | 14 ++++----- .../command.tests.ps1 | 4 +-- .../string.tests.ps1 | 2 +- .../xml.tests.ps1 | 4 +-- 8 files changed, 37 insertions(+), 26 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 index f8ac581f8..88dd27310 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Archive/Pester.Commands.Cmdlets.Archive.Tests.ps1 @@ -8,11 +8,22 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { AfterAll { $global:ProgressPreference = $_progressPreference + $env:PSMODULEPATH = $_modulePath } BeforeAll { + # remove the archive module forcefully, to be sure we get the correct version + if ( Get-Module Microsoft.PowerShell.Archive. ) { + Remove-Module Microsoft.PowerShell.Archive -force + } + # Version comparisons should use a System.Version rather than SemanticVersion + $PSVersion = $PSVersionTable.PSVersion -as [Version] # Write-Progress not supported yet on Core $_progressPreference = $ProgressPreference - if ( $IsCore ) { $global:ProgressPreference = "SilentlyContinue" } + # we need to be sure that we get the correct archive module + $_modulePath = $env:PSMODULEPATH + $powershellexe = (get-process -pid $PID).MainModule.FileName + $env:PSMODULEPATH = join-path ([io.path]::GetDirectoryName($powershellexe)) Modules + if ( $IsCoreCLR ) { $global:ProgressPreference = "SilentlyContinue" } Setup -d SourceDir Setup -d SourceDir/ChildDir-1 @@ -37,7 +48,7 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { function Add-CompressionAssemblies { Add-Type -AssemblyName System.IO.Compression - if (($psedition -eq "Core") -or $IsCore ) + if (($psedition -eq "Core") -or $IsCoreCLR ) { Add-Type -AssemblyName System.IO.Compression.ZipFile } @@ -259,7 +270,7 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { It "Validate errors from Compress-Archive when invalid path (non-existing path / non-filesystem path) is supplied for Path or LiteralPath parameters" { CompressArchiveInValidPathValidator "$TestDrive/InvalidPath" $TestDrive "$TestDrive/InvalidPath" "ArchiveCmdletPathNotFound,Compress-Archive" - if ( ! $IsCore ) { + if ( ! $IsCoreCLR ) { CompressArchiveInValidPathValidator "HKLM:/SOFTWARE" $TestDrive "HKLM:/SOFTWARE" "PathNotFound,Compress-Archive" } CompressArchiveInValidPathValidator "$TestDrive" "$TestDrive/NonExistingDirectory/sample.zip" "$TestDrive/NonExistingDirectory/sample.zip" "ArchiveCmdletPathNotFound,Compress-Archive" @@ -267,7 +278,7 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { $path = @("$TestDrive", "$TestDrive/InvalidPath") CompressArchiveInValidPathValidator $path $TestDrive "$TestDrive/InvalidPath" "ArchiveCmdletPathNotFound,Compress-Archive" - if ( ! $IsCore ) { + if ( ! $IsCoreCLR ) { $path = @("$TestDrive", "HKLM:/SOFTWARE") CompressArchiveInValidPathValidator $path $TestDrive "HKLM:/SOFTWARE" "PathNotFound,Compress-Archive" } @@ -375,7 +386,7 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { $destinationPath | Should Exist } # This test requires a fix in PS5 to support reading paths with square bracket - It "Validate that Compress-Archive cmdlet can accept LiteralPath parameter with Special Characters" -skip:($PSVersionTable.psversion -lt "5.0") { + It "Validate that Compress-Archive cmdlet can accept LiteralPath parameter with Special Characters" -skip:($PSVersion -lt "5.0") { $sourcePath = "$TestDrive/SourceDir/ChildDir-1/Sample[]File.txt" "Some Random Content" | Out-File -LiteralPath $sourcePath $destinationPath = "$TestDrive/SampleSingleFileWithSpecialCharacters.zip" @@ -430,7 +441,7 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { } } # This test requires a fix in PS5 to support reading paths with square bracket - It "Validate that Compress-Archive cmdlet can accept LiteralPath parameter for a directory with Special Characters in the directory name" -skip:($PSVersionTable.psversion -lt "5.0") { + It "Validate that Compress-Archive cmdlet can accept LiteralPath parameter for a directory with Special Characters in the directory name" -skip:($PSVersion -lt "5.0") { $sourcePath = "$TestDrive/Source[]Dir/ChildDir[]-1" New-Item $sourcePath -Type Directory | Out-Null "Some Random Content" | Out-File -LiteralPath "$sourcePath/Sample[]File.txt" @@ -460,7 +471,7 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { # Remove-Item -LiteralPath $destinationPath -Force } } - It "Validate that Source Path can be at SystemDrive location" -skip:($IsCore) { + It "Validate that Source Path can be at SystemDrive location" -skip:($IsCoreCLR) { $sourcePath = "$env:SystemDrive/SourceDir" $destinationPath = "$TestDrive/SampleFromSystemDrive.zip" New-Item $sourcePath -Type Directory | Out-Null @@ -678,7 +689,7 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { try { Expand-Archive -Path "$TestDrive/NonExistingArchive" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } catch { $_.FullyQualifiedErrorId | Should Be "ArchiveCmdletPathNotFound,Expand-Archive" } - if ( ! $IsCore ) { + if ( ! $IsCoreCLR ) { try { Expand-Archive -Path "HKLM:/SOFTWARE" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } catch { $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" } } @@ -686,7 +697,7 @@ Describe "Test suite for Microsoft.PowerShell.Archive module" -Tags "CI" { try { Expand-Archive -LiteralPath "$TestDrive/NonExistingArchive" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } catch { $_.FullyQualifiedErrorId | Should Be "ArchiveCmdletPathNotFound,Expand-Archive" } - if ( ! $IsCore ) { + if ( ! $IsCoreCLR ) { try { Expand-Archive -LiteralPath "HKLM:/SOFTWARE" -DestinationPath "$TestDrive/SourceDir"; throw "Expand-Archive did NOT throw expected error" } catch { $_.FullyQualifiedErrorId | Should Be "PathNotFound,Expand-Archive" } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 index 49f4e7cfa..8888b9b5a 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Copy.Item.Tests.ps1 @@ -7,7 +7,7 @@ # If PS Remoting is not available, do not run the suite. function ShouldRun { - if ( $IsCore ) { return $false } + if ( $IsCoreCLR ) { return $false } $result = Invoke-Command -ComputerName . -ScriptBlock {1} -ErrorAction SilentlyContinue return ($result -eq 1) } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 index b5437fc7e..f275a4524 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/FormatHex.Tests.ps1 @@ -189,7 +189,7 @@ Describe "FormatHex" -tags "CI" { $result | Should Not BeNullOrEmpty $result.Count | should be 2 $result[0].ToString() | Should be "00000000 54 68 69 73 20 69 73 20 61 20 62 69 74 20 6D 6F This is a bit mo" - if ( $IsCore ) { + if ( $IsCoreCLR ) { $result[1].ToString() | Should be "00000010 72 65 20 74 65 78 74 re text " } } @@ -199,7 +199,7 @@ Describe "FormatHex" -tags "CI" { $result = Get-Content $InputFile1 -Encoding Byte | Format-Hex $result | Should Not BeNullOrEmpty $result.GetType().Name | Should Be "ByteCollection" - if ( $IsCore ) { + if ( $IsCoreCLR ) { $result.ToString() | Should be "00000000 48 65 6C 6C 6F 20 57 6F 72 6C 64 Hello World " } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 index 04bc41d89..fcc8c9a6e 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ImportExportCSV.Delimiter.Tests.ps1 @@ -18,7 +18,7 @@ ) function Set-delimiter { param ( $delimiter ) - if ( $IsCore ) { + if ( $IsCoreCLR ) { $enCulture.TextInfo.ListSeparator = $delimiter [System.Globalization.CultureInfo]::CurrentCulture = $enCulture } @@ -28,7 +28,7 @@ } } AfterEach { - if ( $IsCore ) { + if ( $IsCoreCLR ) { $enCulture.TextInfo.ListSeparator = $defaultDelimiter [System.Globalization.CultureInfo]::CurrentCulture = $enCulture } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 index 6fea81ea0..0c180752c 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Pester.Commands.Cmdlets.Json.Tests.ps1 @@ -109,7 +109,7 @@ Describe "Json Tests" -Tags "Feature" { $response.d.Name.First | Should Match "Joel" } - It "Convert to Json using PSObject" -pending:($IsCore) { + It "Convert to Json using PSObject" -pending:($IsCoreCLR) { $response = ConvertFrom-Json '{"d":{"__type":"SimpleJsonObject","Name":{"First":"Joel","Last":"Wood"},"Greeting":"Hello"}}' @@ -169,7 +169,7 @@ Describe "Json Tests" -Tags "Feature" { $response2 | Should Be $result3 } - It "Convert to Json using hashtable" -pending:($IsCore) { + It "Convert to Json using hashtable" -pending:($IsCoreCLR) { $nameHash = @{First="Joe1";Last="Wood"} $dHash = @{Name=$nameHash; Greeting="Hello"} @@ -365,7 +365,7 @@ Describe "Validate Json serialization" -Tags "CI" { $testCases = @( @{ TestInput = 0 - ToJson = if ( $IsCore ) { '"\u0000"' } else { 'null' } + ToJson = if ( $IsCoreCLR ) { '"\u0000"' } else { 'null' } FromJson = '' } @{ @@ -555,12 +555,12 @@ Describe "Validate Json serialization" -Tags "CI" { } @{ TestInput = 38 - ToJson = if ( $IsCore ) { '"&"' } else { '"\u0026"' } + ToJson = if ( $IsCoreCLR ) { '"&"' } else { '"\u0026"' } FromJson = '&' } @{ TestInput = 39 - ToJson = if ( $IsCore ) { '"''"' } else { '"\u0027"' } + ToJson = if ( $IsCoreCLR ) { '"''"' } else { '"\u0027"' } FromJson = "'" } @{ @@ -665,7 +665,7 @@ Describe "Validate Json serialization" -Tags "CI" { } @{ TestInput = 60 - ToJson = if ( $IsCore ) { '"<"' } else { '"\u003c"' } + ToJson = if ( $IsCoreCLR ) { '"<"' } else { '"\u003c"' } FromJson = '<' } @{ @@ -675,7 +675,7 @@ Describe "Validate Json serialization" -Tags "CI" { } @{ TestInput = 62 - ToJson = if ( $IsCore ) { '">"' } else { '"\u003e"' } + ToJson = if ( $IsCoreCLR ) { '">"' } else { '"\u003e"' } FromJson = '>' } @{ diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 index 6aeb05ad2..443abc0a3 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/command.tests.ps1 @@ -11,7 +11,7 @@ if ( test-path $actualLogFile ) { Remove-Item $actualLogFile } } - It "LogicalOperationStack works" -pending:($IsCore) { + It "LogicalOperationStack works" -pending:($IsCoreCLR) { $keyword = "Trace_Command_ListenerOption_LogicalOperationStack_Foo" $stack = [System.Diagnostics.Trace]::CorrelationManager.LogicalOperationStack $stack.Push($keyword) @@ -22,7 +22,7 @@ $log.Count | Should BeGreaterThan 0 } - It "Callstack works" -pending:($IsCore) { + It "Callstack works" -pending:($IsCoreCLR) { Trace-Command -Name * -Expression {write-output Foo} -ListenerOption Callstack -FilePath $logfile $log = Get-Content $logfile | Where-Object {$_ -like "*Callstack= * System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)*"} $log.Count | Should BeGreaterThan 0 diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 index 5f7c0e776..0b367b334 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/string.tests.ps1 @@ -36,7 +36,7 @@ (select-string -LiteralPath $fileNameWithDots "b").count | Should Be 2 } - It "Network path" -skip:($IsCore) { + It "Network path" -skip:($IsCoreCLR) { (select-string -LiteralPath $fileNameAsNetworkPath "b").count | Should Be 2 } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 index 7c402aea6..71b124682 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/xml.tests.ps1 @@ -28,13 +28,13 @@ $testcases += [TestData]::new('literalpath with relative paths', @{LiteralPath = $fileName.Name; XPath = 'Root'}) $testcases += [TestData]::new('literalpath with absolute paths', @{LiteralPath = $fileName.FullName; XPath = 'Root'}) $testcases += [TestData]::new('literalpath with path with dots', @{LiteralPath = $fileNameWithDots; XPath = 'Root'}) - if ( ! $IsCore ) { + if ( ! $IsCoreCLR ) { $testcases += [TestData]::new('literalpath with network path', @{LiteralPath = $fileNameAsNetworkPath; XPath = 'Root'}) } $testcases += [TestData]::new('path with relative paths', @{Path = $fileName.Name; XPath = 'Root'}) $testcases += [TestData]::new('path with absolute paths', @{Path = $fileName.FullName; XPath = 'Root'}) $testcases += [TestData]::new('path with path with dots', @{Path = $fileNameWithDots; XPath = 'Root'}) - if ( ! $IsCore ) { + if ( ! $IsCoreCLR ) { $testcases += [TestData]::new('path with network path', @{Path = $fileNameAsNetworkPath; XPath = 'Root'}) } } From d6b8159e5c3e8b7ad4e4c40b9f1a7ab3b9f357e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Nikoli=C4=87?= Date: Tue, 2 Aug 2016 22:12:00 +0200 Subject: [PATCH 23/25] Update installation/linux.md Fixing typo. --- docs/installation/linux.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation/linux.md b/docs/installation/linux.md index 00aab4e91..f74443c3f 100644 --- a/docs/installation/linux.md +++ b/docs/installation/linux.md @@ -22,7 +22,7 @@ sudo apt-get install libunwind8 libicu52 sudo dpkg -i powershell_6.0.0-alpha.7-1_amd64.deb ``` -> Please note that that Ubuntu 16.04 is not yet supported, but coming soon! +> Please note that Ubuntu 16.04 is not yet supported, but coming soon! [Ubuntu 14.04]: http://releases.ubuntu.com/14.04/ From 99249d0ff4fc5ea4213acff456d30858b132a6f8 Mon Sep 17 00:00:00 2001 From: Sergei Vorobev Date: Tue, 2 Aug 2016 12:45:21 -0700 Subject: [PATCH 24/25] Update building instructions to use correct TOP directories --- docs/building/linux.md | 6 +++--- docs/building/osx.md | 2 +- docs/building/windows-core.md | 2 +- docs/building/windows-full.md | 13 +++++-------- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/docs/building/linux.md b/docs/building/linux.md index d76266823..a95d5a94a 100644 --- a/docs/building/linux.md +++ b/docs/building/linux.md @@ -106,7 +106,7 @@ Start-PSBuild Congratulations! If everything went right, PowerShell is now built. The `Start-PSBuild` script will output the location of the executable: -`./src/powershell/bin/Linux/netcoreapp1.0/ubuntu.14.04-x64/powershell`. +`./src/powershell-unix/bin/Linux/netcoreapp1.0/ubuntu.14.04-x64/powershell`. You should now be running the `powershell` that you just built, if your run the above executable. You can run our cross-platform Pester tests with `Start-PSPester`, and our xUnit tests with `Start-PSxUnit`. @@ -129,7 +129,7 @@ make test popd ``` -This library will be emitted in the `src/powershell` project, +This library will be emitted in the `src/powershell-unix` project, where `dotnet` consumes it as "content" and thus automatically deploys it. Build the managed projects @@ -141,7 +141,7 @@ The `--configuration Linux` flag is necessary to ensure that the preprocessor de ```sh dotnet restore -cd src/powershell +cd src/powershell-unix dotnet build --configuration Linux ``` diff --git a/docs/building/osx.md b/docs/building/osx.md index 50f77dc70..f844ceb03 100644 --- a/docs/building/osx.md +++ b/docs/building/osx.md @@ -76,6 +76,6 @@ download the `pkg` from our GitHub releases page using your browser, complete th start a `powershell` session, and use `Start-PSBuild` from the module. The output directory will be slightly different because your runtime identifier is different. -PowerShell will be at `./src/powershell/bin/Linux/netcoreapp1.0/osx.10.11-x64/powershell`, +PowerShell will be at `./src/powershell-unix/bin/Linux/netcoreapp1.0/osx.10.11-x64/powershell`, or `osx.10.10` depending on your operating system version. Note that configration is still `Linux` because it would be silly to make yet another separate configuration when it's used soley to work-around a CLI issue. diff --git a/docs/building/windows-core.md b/docs/building/windows-core.md index 6ba89241e..7388f24f2 100644 --- a/docs/building/windows-core.md +++ b/docs/building/windows-core.md @@ -72,7 +72,7 @@ Start-PSBuild ``` Congratulations! If everything went right, PowerShell is now built and -executable as `./src/powershell/bin/Debug/netcoreapp1.0/win10-x64/powershell`. +executable as `./src/powershell-win-core/bin/Debug/netcoreapp1.0/win10-x64/powershell`. This location is of the form `./[project]/bin/[configuration]/[framework]/[rid]/[binary name]`, and our diff --git a/docs/building/windows-full.md b/docs/building/windows-full.md index 56b06e9b9..a84b0a5a4 100644 --- a/docs/building/windows-full.md +++ b/docs/building/windows-full.md @@ -48,14 +48,11 @@ Build using our module Use `Start-PSBuild -FullCLR` from the `build.psm1` module. -Because the `ConsoleHost` project (*not* the `Host` project) is a -library and not an application (in the sense that .NET CLI does not -emit a native executable using .NET Core's `corehost`), it targets the -framework `netstandard1.6`, *not* `netcoreapp1.0`, and the build -output will *not* have a runtime identifier in the path. +The output location of `powershell.exe` will be -Thus the output location of `powershell.exe` will be -`./src/Microsoft.PowerShell.ConsoleHost/bin/Debug/net451/powershell.exe` +``` +.\src\powershell-win-full\bin\Debug\net451\win10-x64\publish\powershell.exe +``` Build manually ============== @@ -99,7 +96,7 @@ This command has a reasonable default to run `powershell.exe` from the build out If you are building an unusual configuration (i.e. not `Debug`), you can explicitly specify path to the bin directory ```powershell -Start-DevPowerShell -FullCLR -binDir .\src\Microsoft.PowerShell.ConsoleHost\bin\Debug\net451 +Start-DevPowerShell -FullCLR -binDir .\src\powershell-win-full\bin\Debug\net451\win10-x64\publish ``` Or more programmatically: From b38256aab17cf14401349c816f90698fd624bd14 Mon Sep 17 00:00:00 2001 From: Angel Calvo Date: Sun, 31 Jul 2016 10:09:10 -0700 Subject: [PATCH 25/25] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made some changes on package installation table - I noticed some inconsistencies some places using How to Install, others Installation Instructions. So I cleaned up, and removed “How to” in favor of “install” and Installation Instuctions. Update README.md Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1927d0a17..86cf7e430 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,10 @@ You can download and install a PowerShell package for any of the following platf | Platform | Releases | How to Install | |--------------|--------------------|--------------------------------| -| Windows | [.msi][rl-windows] | [How to Install][in-windows] | -| Ubuntu 14.04 | [.deb][rl-ubuntu] | [How to Install][in-ubuntu] | -| CentOS 7 | [.rpm][rl-centos] | [How to Install][in-centos] | -| OS X 10.11 | [.pkg][rl-osx] | [How to Install][in-osx] | +| Windows | [.msi][rl-windows] | [Instructions][in-windows] | +| Ubuntu 14.04 | [.deb][rl-ubuntu] | [Instructions][in-ubuntu] | +| CentOS 7 | [.rpm][rl-centos] | [Instructions][in-centos] | +| OS X 10.11 | [.pkg][rl-osx] | [Instructions][in-osx] | [rl-windows]: https://github.com/PowerShell/PowerShell/releases/download/v6.0.0-alpha.7/PowerShell_6.0.0.7.msi [rl-ubuntu]: https://github.com/PowerShell/PowerShell/releases/download/v6.0.0-alpha.7/powershell_6.0.0-alpha.7-1_amd64.deb