Skip to content

Commit

Permalink
Added full path from JSON objects #1174 (#1175)
Browse files Browse the repository at this point in the history
  • Loading branch information
BernieWhite authored Jul 23, 2022
1 parent 835687e commit cb6f3b0
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 6 deletions.
8 changes: 7 additions & 1 deletion docs/CHANGELOG-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,17 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers

## Unreleased

What's changed since pre-release v2.3.0-B0030:

- General improvements:
- Added support for full path from JSON objects by @BernieWhite.
[#1174](https://github.com/microsoft/PSRule/issues/1174)

## v2.3.0-B0030 (pre-release)

What's changed since pre-release v2.3.0-B0015:

- General improvements
- General improvements:
- Improved reporting of full object path from pre-processed results by @BernieWhite.
[#1169](https://github.com/microsoft/PSRule/issues/1169)

Expand Down
3 changes: 3 additions & 0 deletions src/PSRule/Common/JsonConverters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ private static bool SkipComments(JsonReader reader)
private static PSObject ReadObject(JsonReader reader, bool bindTargetInfo, TargetSourceInfo sourceInfo)
{
SkipComments(reader);
var path = reader.Path;
if (reader.TokenType != JsonToken.StartObject || !reader.Read())
throw new PipelineSerializationException(PSRuleResources.ReadJsonFailed);

Expand Down Expand Up @@ -276,6 +277,8 @@ private static PSObject ReadObject(JsonReader reader, bool bindTargetInfo, Targe
{
result.UseTargetInfo(out var info);
info.SetSource(sourceInfo?.File, lineNumber, linePosition);
if (string.IsNullOrEmpty(info.Path))
info.Path = path;
}
return result;
}
Expand Down
10 changes: 9 additions & 1 deletion src/PSRule/Common/PSObjectExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Management.Automation;
using System.Threading;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PSRule.Data;
using PSRule.Runtime;

Expand Down Expand Up @@ -118,7 +119,14 @@ public static TargetIssueInfo[] GetIssueInfo(this PSObject o)

public static string GetTargetPath(this PSObject o)
{
return o.TryTargetInfo(out var targetInfo) ? targetInfo.Path : string.Empty;
if (o == null)
return string.Empty;

if (o.TryTargetInfo(out var targetInfo))
return targetInfo.Path;

var baseObject = o.BaseObject;
return baseObject is JToken token ? token.Path : string.Empty;
}

public static void ConvertTargetInfoProperty(this PSObject o)
Expand Down
4 changes: 1 addition & 3 deletions src/PSRule/Runtime/PSRuleMemberInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@

namespace PSRule.Runtime
{
[DebuggerDisplay("Instance = {_Instance}")]
[DebuggerDisplay("Path = {Path}, File = {File}")]
internal sealed class PSRuleTargetInfo : PSMemberInfo
{
internal const string PropertyName = "_PSRule";

private readonly string _Instance = Guid.NewGuid().ToString();

public PSRuleTargetInfo()
{
SetMemberName(PropertyName);
Expand Down
2 changes: 2 additions & 0 deletions tests/PSRule.Tests/InputFormatDeserializerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ public void DeserializeObjectsJson()
actual[0].Value.TryTargetInfo(out var info1);
actual[1].Value.TryTargetInfo(out var info2);
Assert.Equal("some-file.json", info1.Source[0].File);
Assert.Equal("master.items[0]", info1.Path);
Assert.NotNull(info2.Source[0]);
Assert.Equal("[1]", info2.Path);

// Single item
actual = PipelineReceiverActions.ConvertFromJson(GetJsonContent("Single"), PipelineReceiverActions.PassThru).ToArray();
Expand Down
47 changes: 46 additions & 1 deletion tests/PSRule.Tests/PipelineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
using System.IO;
using System.Linq;
using System.Management.Automation;
using Newtonsoft.Json.Linq;
using PSRule.Configuration;
using PSRule.Pipeline;
using PSRule.Resources;
using PSRule.Rules;
using Xunit;

namespace PSRule
Expand Down Expand Up @@ -45,6 +47,45 @@ public void InvokePipeline()
pipeline.End();
}

[Fact]
public void InvokePipelineWithJObject()
{
var parent = new JObject
{
["resources"] = new JArray(new object[] {
new JObject
{
["Name"] = "TestValue"
},
new JObject
{
["Name"] = "TestValue2"
}
})
};

var option = GetOption();
option.Rule.Include = new string[] { "ScriptReasonTest" };
option.Input.Format = InputFormat.File;
var builder = PipelineBuilder.Invoke(GetSource(), option, null);
var writer = new TestWriter(option);
var pipeline = builder.Build(writer);

Assert.NotNull(pipeline);
pipeline.Begin();
pipeline.Process(PSObject.AsPSObject(parent["resources"][0]));
pipeline.Process(PSObject.AsPSObject(parent["resources"][1]));
pipeline.End();

var actual = (writer.Output[0] as InvokeResult).AsRecord().FirstOrDefault();
Assert.Equal(RuleOutcome.Pass, actual.Outcome);

actual = (writer.Output[1] as InvokeResult).AsRecord().FirstOrDefault();
Assert.Equal(RuleOutcome.Fail, actual.Outcome);
Assert.Equal("Name", actual.Detail.Reason.First().Path);
Assert.Equal("resources[1].Name", actual.Detail.Reason.First().FullPath);
}

[Fact]
public void BuildGetPipeline()
{
Expand Down Expand Up @@ -158,9 +199,13 @@ public void PipelineWithSource()
items = writer.Output.OfType<InvokeResult>().SelectMany(i => i.AsRecord()).ToArray();
Assert.Equal(4, items.Length);
Assert.Equal("master.items[0].Name", items[0].Detail.Reason.First().FullPath);
Assert.Equal("Name", items[1].Detail.Reason.First().FullPath);
Assert.Equal("Name", items[0].Detail.Reason.First().Path);
Assert.Equal("[1].Name", items[1].Detail.Reason.First().FullPath);
Assert.Equal("Name", items[1].Detail.Reason.First().Path);
Assert.Equal("resources[0].Name", items[2].Detail.Reason.First().FullPath);
Assert.Equal("Name", items[2].Detail.Reason.First().Path);
Assert.Equal("Name", items[3].Detail.Reason.First().FullPath);
Assert.Equal("Name", items[3].Detail.Reason.First().Path);

// With IgnoreObjectSource
option.Rule.Include = new string[] { "FromFile1" };
Expand Down

0 comments on commit cb6f3b0

Please sign in to comment.