зеркало из https://github.com/microsoft/PSRule.git
Родитель
76b184999e
Коммит
2ffa9a0ade
|
@ -3,52 +3,20 @@
|
||||||
|
|
||||||
# Synopsis: Check for recommended community files
|
# Synopsis: Check for recommended community files
|
||||||
Rule 'OpenSource.Community' -Type 'System.IO.DirectoryInfo', 'PSRule.Data.RepositoryInfo' {
|
Rule 'OpenSource.Community' -Type 'System.IO.DirectoryInfo', 'PSRule.Data.RepositoryInfo' {
|
||||||
$requiredFiles = @(
|
$Assert.FilePath($TargetObject, 'FullName', @('CHANGELOG.md'));
|
||||||
'CHANGELOG.md'
|
$Assert.FilePath($TargetObject, 'FullName', @('LICENSE', 'LICENSE.txt'));
|
||||||
'LICENSE.txt'
|
$Assert.FilePath($TargetObject, 'FullName', @('CODE_OF_CONDUCT.md'));
|
||||||
'CODE_OF_CONDUCT.md'
|
$Assert.FilePath($TargetObject, 'FullName', @('CONTRIBUTING.md'));
|
||||||
'CONTRIBUTING.md'
|
$Assert.FilePath($TargetObject, 'FullName', @('SECURITY.md'));
|
||||||
'SECURITY.md'
|
$Assert.FilePath($TargetObject, 'FullName', @('README.md'));
|
||||||
'README.md'
|
$Assert.FilePath($TargetObject, 'FullName', @('.github/CODEOWNERS'));
|
||||||
'.github/CODEOWNERS'
|
$Assert.FilePath($TargetObject, 'FullName', @('.github/PULL_REQUEST_TEMPLATE.md'));
|
||||||
'.github/PULL_REQUEST_TEMPLATE.md'
|
|
||||||
)
|
|
||||||
Test-Path -Path $TargetObject.FullName;
|
|
||||||
for ($i = 0; $i -lt $requiredFiles.Length; $i++) {
|
|
||||||
$filePath = Join-Path -Path $TargetObject.FullName -ChildPath $requiredFiles[$i];
|
|
||||||
$Assert.Create((Test-Path -Path $filePath -PathType Leaf), "$($requiredFiles[$i]) does not exist");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Synopsis: Check for license in code files
|
# Synopsis: Check for license in code files
|
||||||
Rule 'OpenSource.License' -Type 'System.IO.FileInfo', 'PSRule.Data.InputFileInfo', '.cs', '.ps1', '.psd1', '.psm1' -If { $TargetObject.Extension -in '.cs', '.ps1', '.psd1', '.psm1' } {
|
Rule 'OpenSource.License' -Type '.cs', '.ps1', '.psd1', '.psm1' {
|
||||||
$commentPrefix = "`# ";
|
$Assert.FileHeader($TargetObject, 'FullName', @(
|
||||||
if ($TargetObject.Extension -eq '.cs') {
|
'Copyright (c) Microsoft Corporation.'
|
||||||
$commentPrefix = '// '
|
'Licensed under the MIT License.'
|
||||||
}
|
));
|
||||||
$header = GetLicenseHeader -CommentPrefix $commentPrefix;
|
|
||||||
$content = Get-Content -Path $TargetObject.FullName -Raw;
|
|
||||||
$content.StartsWith($header);
|
|
||||||
}
|
|
||||||
|
|
||||||
function global:GetLicenseHeader {
|
|
||||||
[CmdletBinding()]
|
|
||||||
[OutputType([String])]
|
|
||||||
param (
|
|
||||||
[Parameter(Mandatory = $True)]
|
|
||||||
[String]$CommentPrefix
|
|
||||||
)
|
|
||||||
process {
|
|
||||||
$text = @(
|
|
||||||
'Copyright (c) Microsoft Corporation.'
|
|
||||||
'Licensed under the MIT License.'
|
|
||||||
)
|
|
||||||
$builder = [System.Text.StringBuilder]::new();
|
|
||||||
foreach ($line in $text) {
|
|
||||||
$Null = $builder.Append($CommentPrefix);
|
|
||||||
$Null = $builder.Append($line);
|
|
||||||
$Null = $builder.Append([System.Environment]::NewLine);
|
|
||||||
}
|
|
||||||
return $builder.ToString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
- Engine features:
|
||||||
|
- Added file assertion helpers `FileHeader`, and `FilePath`. [#534](https://github.com/microsoft/PSRule/issues/534)
|
||||||
|
- `FileHeader` checks for a comment header in the file.
|
||||||
|
- `FilePath` checks that a file path, optionally with suffixes exist.
|
||||||
- Bug fixes:
|
- Bug fixes:
|
||||||
- Fixed out of bounds exception when empty markdown documentation is used. [#516](https://github.com/microsoft/PSRule/issues/516)
|
- Fixed out of bounds exception when empty markdown documentation is used. [#516](https://github.com/microsoft/PSRule/issues/516)
|
||||||
|
|
||||||
|
|
|
@ -235,6 +235,8 @@ The following conceptual topics exist in the `PSRule` module:
|
||||||
- [Assert](docs/concepts/PSRule/en-US/about_PSRule_Assert.md)
|
- [Assert](docs/concepts/PSRule/en-US/about_PSRule_Assert.md)
|
||||||
- [Contains](docs/concepts/PSRule/en-US/about_PSRule_Assert.md#contains)
|
- [Contains](docs/concepts/PSRule/en-US/about_PSRule_Assert.md#contains)
|
||||||
- [EndsWith](docs/concepts/PSRule/en-US/about_PSRule_Assert.md#endswith)
|
- [EndsWith](docs/concepts/PSRule/en-US/about_PSRule_Assert.md#endswith)
|
||||||
|
- [FileHeader](docs/concepts/PSRule/en-US/about_PSRule_Assert.md#fileheader)
|
||||||
|
- [FilePath](docs/concepts/PSRule/en-US/about_PSRule_Assert.md#filepath)
|
||||||
- [Greater](docs/concepts/PSRule/en-US/about_PSRule_Assert.md#greater)
|
- [Greater](docs/concepts/PSRule/en-US/about_PSRule_Assert.md#greater)
|
||||||
- [GreaterOrEqual](docs/concepts/PSRule/en-US/about_PSRule_Assert.md#greaterorequal)
|
- [GreaterOrEqual](docs/concepts/PSRule/en-US/about_PSRule_Assert.md#greaterorequal)
|
||||||
- [HasDefaultValue](docs/concepts/PSRule/en-US/about_PSRule_Assert.md#hasdefaultvalue)
|
- [HasDefaultValue](docs/concepts/PSRule/en-US/about_PSRule_Assert.md#hasdefaultvalue)
|
||||||
|
|
|
@ -17,6 +17,8 @@ The following built-in assertion methods are provided:
|
||||||
|
|
||||||
- [Contains](#contains) - The field value must contain at least one of the strings.
|
- [Contains](#contains) - The field value must contain at least one of the strings.
|
||||||
- [EndsWith](#endswith) - The field value must match at least one suffix.
|
- [EndsWith](#endswith) - The field value must match at least one suffix.
|
||||||
|
- [FileHeader](#fileheader) - The file must contain a comment header.
|
||||||
|
- [FilePath](#filepath) - The file path must exist.
|
||||||
- [Greater](#greater) - The field value must be greater.
|
- [Greater](#greater) - The field value must be greater.
|
||||||
- [GreaterOrEqual](#greaterorequal) - The field value must be greater or equal to.
|
- [GreaterOrEqual](#greaterorequal) - The field value must be greater or equal to.
|
||||||
- [HasDefaultValue](#hasdefaultvalue) - The object should not have the field or the field value is set to the default value.
|
- [HasDefaultValue](#hasdefaultvalue) - The object should not have the field or the field value is set to the default value.
|
||||||
|
@ -129,6 +131,8 @@ The following parameters are accepted:
|
||||||
- `suffix` - One or more suffixes to compare the field value with. Only one suffix must match.
|
- `suffix` - One or more suffixes to compare the field value with. Only one suffix must match.
|
||||||
- `caseSensitive` (optional) - Use a case sensitive compare of the field value. Case is ignored by default.
|
- `caseSensitive` (optional) - Use a case sensitive compare of the field value. Case is ignored by default.
|
||||||
|
|
||||||
|
Reasons include:
|
||||||
|
|
||||||
- _The parameter 'inputObject' is null._
|
- _The parameter 'inputObject' is null._
|
||||||
- _The parameter 'field' is null or empty._
|
- _The parameter 'field' is null or empty._
|
||||||
- _The field '{0}' does not exist._
|
- _The field '{0}' does not exist._
|
||||||
|
@ -144,6 +148,83 @@ Rule 'EndsWith' {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### FileHeader
|
||||||
|
|
||||||
|
The `FileHeader` assertion method checks a file for a comment header.
|
||||||
|
When comparing the file header, the format of line comments are automatically detected by file extension.
|
||||||
|
Single line comments are supported. Multi-line comments are not supported.
|
||||||
|
|
||||||
|
The following parameters are accepted:
|
||||||
|
|
||||||
|
- `inputObject` - The object being checked for the specified field.
|
||||||
|
- `field` - The name of the field containing a valid file path.
|
||||||
|
- `header` - One or more lines of a header to compare with file contents.
|
||||||
|
- `prefix` (optional) - An optional comment prefix for each line.
|
||||||
|
By default a comment prefix will automatically detected based on file extension.
|
||||||
|
When set, detection by file extension is skipped.
|
||||||
|
|
||||||
|
Prefix detection for line comments is supported with the following file extensions:
|
||||||
|
|
||||||
|
- `.cs`, `.ts`, `.js`, `.fs`, `.go`, `.php`, `.cpp`, `.h` - Use a prefix of (`// `).
|
||||||
|
- `.ps1`, `.psd1`, `.psm1`, `.yaml`, `.yml`, `.r`, `.py`, `.sh`, `.tf`, `.tfvars`, `.gitignore`, `.pl` - Use a prefix of (`# `).
|
||||||
|
- `.sql`, `.lau` - Use a prefix of (`-- `).
|
||||||
|
|
||||||
|
Reasons include:
|
||||||
|
|
||||||
|
- _The parameter 'inputObject' is null._
|
||||||
|
- _The parameter 'field' is null or empty._
|
||||||
|
- _The field '{0}' does not exist._
|
||||||
|
- _The field value '{0}' is not a string._
|
||||||
|
- _The file '{0}' does not exist._
|
||||||
|
- _The header was not set._
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
Rule 'FileHeader' {
|
||||||
|
$Assert.FileHeader($TargetObject, 'FullName', @(
|
||||||
|
'Copyright (c) Microsoft Corporation.'
|
||||||
|
'Licensed under the MIT License.'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### FilePath
|
||||||
|
|
||||||
|
The `FilePath` assertion method checks the file exists.
|
||||||
|
Checks use OS case-sensitivity rules.
|
||||||
|
|
||||||
|
The following parameters are accepted:
|
||||||
|
|
||||||
|
- `inputObject` - The object being checked for the specified field.
|
||||||
|
- `field` - The name of the field containing a file path.
|
||||||
|
- `suffix` (optional) - Additional file path suffixes to append.
|
||||||
|
When specified each suffix is combined with the file path.
|
||||||
|
Only one full file path must be a valid file for the assertion method to pass.
|
||||||
|
|
||||||
|
Reasons include:
|
||||||
|
|
||||||
|
- _The parameter 'inputObject' is null._
|
||||||
|
- _The parameter 'field' is null or empty._
|
||||||
|
- _The field '{0}' does not exist._
|
||||||
|
- _The field value '{0}' is not a string._
|
||||||
|
- _The file '{0}' does not exist._
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
Rule 'FilePath' {
|
||||||
|
$Assert.FilePath($TargetObject, 'FullName', @('CHANGELOG.md'));
|
||||||
|
$Assert.FilePath($TargetObject, 'FullName', @('LICENSE', 'LICENSE.txt'));
|
||||||
|
$Assert.FilePath($TargetObject, 'FullName', @('CODE_OF_CONDUCT.md'));
|
||||||
|
$Assert.FilePath($TargetObject, 'FullName', @('CONTRIBUTING.md'));
|
||||||
|
$Assert.FilePath($TargetObject, 'FullName', @('SECURITY.md'));
|
||||||
|
$Assert.FilePath($TargetObject, 'FullName', @('README.md'));
|
||||||
|
$Assert.FilePath($TargetObject, 'FullName', @('.github/CODEOWNERS'));
|
||||||
|
$Assert.FilePath($TargetObject, 'FullName', @('.github/PULL_REQUEST_TEMPLATE.md'));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Greater
|
### Greater
|
||||||
|
|
||||||
The `Greater` assertion method checks the field value is greater than the specified value.
|
The `Greater` assertion method checks the field value is greater than the specified value.
|
||||||
|
|
|
@ -105,6 +105,24 @@ namespace PSRule.Resources {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to The header was not set..
|
||||||
|
/// </summary>
|
||||||
|
internal static string FileHeader {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("FileHeader", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to The file '{0}' does not exist..
|
||||||
|
/// </summary>
|
||||||
|
internal static string FilePath {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("FilePath", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to The value '{0}' was not > '{1}'..
|
/// Looks up a localized string similar to The value '{0}' was not > '{1}'..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -134,6 +134,12 @@
|
||||||
<value>The field(s) existed: {0}</value>
|
<value>The field(s) existed: {0}</value>
|
||||||
<comment>Included when any of the fields exist and the -Not switch is used.</comment>
|
<comment>Included when any of the fields exist and the -Not switch is used.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="FileHeader" xml:space="preserve">
|
||||||
|
<value>The header was not set.</value>
|
||||||
|
</data>
|
||||||
|
<data name="FilePath" xml:space="preserve">
|
||||||
|
<value>The file '{0}' does not exist.</value>
|
||||||
|
</data>
|
||||||
<data name="Greater" xml:space="preserve">
|
<data name="Greater" xml:space="preserve">
|
||||||
<value>The value '{0}' was not > '{1}'.</value>
|
<value>The value '{0}' was not > '{1}'.</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
@ -421,6 +421,73 @@ namespace PSRule.Runtime
|
||||||
return Fail(ReasonStrings.NotMatchPattern, value, pattern);
|
return Fail(ReasonStrings.NotMatchPattern, value, pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AssertResult FilePath(PSObject inputObject, string field, string[] suffix = null)
|
||||||
|
{
|
||||||
|
// Guard parameters
|
||||||
|
if (GuardNullParam(inputObject, nameof(inputObject), out AssertResult result) ||
|
||||||
|
GuardNullOrEmptyParam(field, nameof(field), out result) ||
|
||||||
|
GuardField(inputObject, field, false, out object fieldValue, out result) ||
|
||||||
|
GuardString(fieldValue, out string value, out result))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (suffix == null || suffix.Length == 0)
|
||||||
|
{
|
||||||
|
if (!TryFilePath(value, out _))
|
||||||
|
return Fail(ReasonStrings.FilePath, value);
|
||||||
|
|
||||||
|
return Pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
var reason = Fail();
|
||||||
|
for (var i = 0; i < suffix.Length; i++)
|
||||||
|
{
|
||||||
|
if (!TryFilePath(Path.Combine(value, suffix[i]), out _))
|
||||||
|
reason.AddReason(ReasonStrings.FilePath, suffix[i]);
|
||||||
|
else
|
||||||
|
return Pass();
|
||||||
|
}
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssertResult FileHeader(PSObject inputObject, string field, string[] header, string prefix = null)
|
||||||
|
{
|
||||||
|
// Guard parameters
|
||||||
|
if (GuardNullParam(inputObject, nameof(inputObject), out AssertResult result) ||
|
||||||
|
GuardNullOrEmptyParam(field, nameof(field), out result) ||
|
||||||
|
GuardField(inputObject, field, false, out object fieldValue, out result) ||
|
||||||
|
GuardString(fieldValue, out string value, out result))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// File does not exist
|
||||||
|
if (!TryFilePath(value, out _))
|
||||||
|
return Fail(ReasonStrings.FilePath, value);
|
||||||
|
|
||||||
|
// No header
|
||||||
|
if (header == null || header.Length == 0)
|
||||||
|
return Pass();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(prefix))
|
||||||
|
prefix = DetectLinePrefix(Path.GetExtension(value));
|
||||||
|
|
||||||
|
var lineNo = 0;
|
||||||
|
foreach (var content in File.ReadLines(value))
|
||||||
|
{
|
||||||
|
if (lineNo >= header.Length)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (content != string.Concat(prefix, header[lineNo]))
|
||||||
|
return Fail(ReasonStrings.FileHeader);
|
||||||
|
|
||||||
|
lineNo++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Catch file has less lines than header
|
||||||
|
if (lineNo < header.Length)
|
||||||
|
return Fail(ReasonStrings.FileHeader);
|
||||||
|
|
||||||
|
return Pass();
|
||||||
|
}
|
||||||
|
|
||||||
#region Helper methods
|
#region Helper methods
|
||||||
|
|
||||||
private static bool IsEmpty(object fieldValue)
|
private static bool IsEmpty(object fieldValue)
|
||||||
|
@ -472,7 +539,7 @@ namespace PSRule.Runtime
|
||||||
private static bool TryString(object obj, out string value)
|
private static bool TryString(object obj, out string value)
|
||||||
{
|
{
|
||||||
value = null;
|
value = null;
|
||||||
if (obj is string svalue)
|
if (GetBaseObject(obj) is string svalue)
|
||||||
{
|
{
|
||||||
value = svalue;
|
value = svalue;
|
||||||
return true;
|
return true;
|
||||||
|
@ -656,10 +723,10 @@ namespace PSRule.Runtime
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool TryFilePath(string uri, out string path)
|
private static bool TryFilePath(string path, out string rootedPath)
|
||||||
{
|
{
|
||||||
path = PSRuleOption.GetRootedPath(uri);
|
rootedPath = PSRuleOption.GetRootedPath(path);
|
||||||
return File.Exists(path);
|
return File.Exists(rootedPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string FormatArray(string[] values)
|
private static string FormatArray(string[] values)
|
||||||
|
@ -697,6 +764,46 @@ namespace PSRule.Runtime
|
||||||
PipelineContext.CurrentThread.ExpressionCache[string.Concat(prefix, key)] = value;
|
PipelineContext.CurrentThread.ExpressionCache[string.Concat(prefix, key)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determine line comment prefix by file extension
|
||||||
|
/// </summary>
|
||||||
|
private static string DetectLinePrefix(string extension)
|
||||||
|
{
|
||||||
|
switch (extension)
|
||||||
|
{
|
||||||
|
case ".cs":
|
||||||
|
case ".ts":
|
||||||
|
case ".js":
|
||||||
|
case ".fs":
|
||||||
|
case ".go":
|
||||||
|
case ".php":
|
||||||
|
case ".cpp":
|
||||||
|
case ".h":
|
||||||
|
return "// ";
|
||||||
|
|
||||||
|
case ".ps1":
|
||||||
|
case ".psd1":
|
||||||
|
case ".psm1":
|
||||||
|
case ".yaml":
|
||||||
|
case ".yml":
|
||||||
|
case ".r":
|
||||||
|
case ".py":
|
||||||
|
case ".sh":
|
||||||
|
case ".tf":
|
||||||
|
case ".tfvars":
|
||||||
|
case ".gitignore":
|
||||||
|
case ".pl":
|
||||||
|
return "# ";
|
||||||
|
|
||||||
|
case ".sql":
|
||||||
|
case ".lua":
|
||||||
|
return "-- ";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Helper methods
|
#endregion Helper methods
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
using PSRule.Pipeline;
|
using PSRule.Pipeline;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Management.Automation;
|
using System.Management.Automation;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
@ -493,6 +495,30 @@ namespace PSRule
|
||||||
Assert.True(assert.NotMatch(value, "notValue", "\\w*2").Result);
|
Assert.True(assert.NotMatch(value, "notValue", "\\w*2").Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void FileHeader()
|
||||||
|
{
|
||||||
|
SetContext();
|
||||||
|
var assert = GetAssertionHelper();
|
||||||
|
|
||||||
|
var value = GetObject((name: "FullName", value: GetSourcePath("FromFile.Rule.ps1")));
|
||||||
|
Assert.True(assert.FileHeader(value, "FullName", new string[] { "Copyright (c) Microsoft Corporation.", "Licensed under the MIT License." }).Result);
|
||||||
|
value = GetObject((name: "FullName", value: GetSourcePath("Baseline.Rule.yaml")));
|
||||||
|
Assert.False(assert.FileHeader(value, "FullName", new string[] { "Copyright (c) Microsoft Corporation.", "Licensed under the MIT License." }).Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void FilePath()
|
||||||
|
{
|
||||||
|
SetContext();
|
||||||
|
var assert = GetAssertionHelper();
|
||||||
|
|
||||||
|
var value = GetObject((name: "FullName", value: GetSourcePath("Baseline.Rule.yaml")));
|
||||||
|
Assert.True(assert.FilePath(value, "FullName").Result);
|
||||||
|
value = GetObject((name: "FullName", value: GetSourcePath("README.zz")));
|
||||||
|
Assert.False(assert.FilePath(value, "FullName").Result);
|
||||||
|
}
|
||||||
|
|
||||||
#region Helper methods
|
#region Helper methods
|
||||||
|
|
||||||
private static void SetContext()
|
private static void SetContext()
|
||||||
|
@ -516,6 +542,11 @@ namespace PSRule
|
||||||
return new Runtime.Assert();
|
return new Runtime.Assert();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetSourcePath(string fileName)
|
||||||
|
{
|
||||||
|
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Helper methods
|
#endregion Helper methods
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,20 @@ Rule 'Assert.EndsWith' {
|
||||||
$Assert.EndsWith($TargetObject, 'Name', '1')
|
$Assert.EndsWith($TargetObject, 'Name', '1')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Synopsis: Test for $Assert.FileHeader
|
||||||
|
Rule 'Assert.FileHeader' {
|
||||||
|
$Assert.FileHeader($TargetObject, 'Path', @(
|
||||||
|
'Copyright (c) Microsoft Corporation.'
|
||||||
|
'Licensed under the MIT License.'
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
# Synopsis: Test for $Assert.FilePath
|
||||||
|
Rule 'Assert.FilePath' {
|
||||||
|
$Assert.FilePath($TargetObject, 'Path')
|
||||||
|
$Assert.FilePath($TargetObject, 'ParentPath', @('PSRule.Assert.Tests.ps1'))
|
||||||
|
}
|
||||||
|
|
||||||
# Synopsis: Test for $Assert.Greater
|
# Synopsis: Test for $Assert.Greater
|
||||||
Rule 'Assert.Greater' {
|
Rule 'Assert.Greater' {
|
||||||
$Assert.Greater($TargetObject, 'CompareNumeric', 2)
|
$Assert.Greater($TargetObject, 'CompareNumeric', 2)
|
||||||
|
|
|
@ -49,6 +49,8 @@ Describe 'PSRule assertions' -Tag 'Assert' {
|
||||||
'Item3'
|
'Item3'
|
||||||
'Item4'
|
'Item4'
|
||||||
)
|
)
|
||||||
|
Path = $PSCommandPath
|
||||||
|
ParentPath = $here
|
||||||
}
|
}
|
||||||
[PSCustomObject]@{
|
[PSCustomObject]@{
|
||||||
'$schema' = "http://json-schema.org/draft-07/schema`#"
|
'$schema' = "http://json-schema.org/draft-07/schema`#"
|
||||||
|
@ -75,6 +77,7 @@ Describe 'PSRule assertions' -Tag 'Assert' {
|
||||||
'item2'
|
'item2'
|
||||||
'item3'
|
'item3'
|
||||||
)
|
)
|
||||||
|
ParentPath = (Join-Path -Path $here -ChildPath 'notapath')
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -162,6 +165,39 @@ Describe 'PSRule assertions' -Tag 'Assert' {
|
||||||
$result[1].Reason | Should -BeLike "The field '*' does not end with '*'.";
|
$result[1].Reason | Should -BeLike "The field '*' does not end with '*'.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
It 'FileHeader' {
|
||||||
|
$result = @($testObject | Invoke-PSRule -Path $ruleFilePath -Name 'Assert.FileHeader');
|
||||||
|
$result | Should -Not -BeNullOrEmpty;
|
||||||
|
$result.Length | Should -Be 2;
|
||||||
|
|
||||||
|
# Positive case
|
||||||
|
$result[0].IsSuccess() | Should -Be $True;
|
||||||
|
$result[0].TargetName | Should -Be 'TestObject1';
|
||||||
|
|
||||||
|
# Negative case
|
||||||
|
$result[1].IsSuccess() | Should -Be $False;
|
||||||
|
$result[1].TargetName | Should -Be 'TestObject2';
|
||||||
|
$result[1].Reason.Length | Should -Be 1;
|
||||||
|
$result[1].Reason | Should -Be "The field 'Path' does not exist.";
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'FilePath' {
|
||||||
|
$result = @($testObject | Invoke-PSRule -Path $ruleFilePath -Name 'Assert.FilePath');
|
||||||
|
$result | Should -Not -BeNullOrEmpty;
|
||||||
|
$result.Length | Should -Be 2;
|
||||||
|
|
||||||
|
# Positive case
|
||||||
|
$result[0].IsSuccess() | Should -Be $True;
|
||||||
|
$result[0].TargetName | Should -Be 'TestObject1';
|
||||||
|
|
||||||
|
# Negative case
|
||||||
|
$result[1].IsSuccess() | Should -Be $False;
|
||||||
|
$result[1].TargetName | Should -Be 'TestObject2';
|
||||||
|
$result[1].Reason.Length | Should -Be 2;
|
||||||
|
$result[1].Reason[0] | Should -Be "The field 'Path' does not exist.";
|
||||||
|
$result[1].Reason[1] | Should -BeLike "The file '*' does not exist.";
|
||||||
|
}
|
||||||
|
|
||||||
It 'Greater' {
|
It 'Greater' {
|
||||||
$result = @($testObject | Invoke-PSRule -Path $ruleFilePath -Name 'Assert.Greater');
|
$result = @($testObject | Invoke-PSRule -Path $ruleFilePath -Name 'Assert.Greater');
|
||||||
$result | Should -Not -BeNullOrEmpty;
|
$result | Should -Not -BeNullOrEmpty;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче