Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions Assets/Tests/Editor/HotReload/HotReloadRunTimingTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;

using NUnit.Framework;

Expand Down Expand Up @@ -113,5 +114,76 @@ public void Complete_TotalBelowThePhases_Throws()

Assert.Throws<ArgumentOutOfRangeException>(() => timing.Complete(329));
}

/// <summary>
/// What: a step measured twice in one run, such as once per group, adds up under one entry,
/// and the steps keep the order they were first seen in.
/// </summary>
[Test]
public void AddDetail_SameStepTwice_SumsAndKeepsFirstSeenOrder()
{
HotReloadRunTiming timing = new HotReloadRunTiming();

timing.AddDetail("plan", 3);
timing.AddDetail("resolve_inputs", 5);
timing.AddDetail("plan", 4);

Assert.That(timing.Details, Is.EqualTo(new[]
{
new KeyValuePair<string, long>("plan", 7),
new KeyValuePair<string, long>("resolve_inputs", 5),
}));
}

/// <summary>
/// What: a negative step time is refused instead of shrinking the step's sum.
/// </summary>
[Test]
public void AddDetail_NegativeMilliseconds_Throws()
{
HotReloadRunTiming timing = new HotReloadRunTiming();

Assert.Throws<ArgumentOutOfRangeException>(() => timing.AddDetail("plan", -1));
}

/// <summary>
/// What: a step without a name is refused, whether the name is empty or null.
/// </summary>
[Test]
public void AddDetail_EmptyStep_Throws()
{
HotReloadRunTiming timing = new HotReloadRunTiming();

Assert.Throws<ArgumentException>(() => timing.AddDetail(string.Empty, 1));
Assert.Throws<ArgumentException>(() => timing.AddDetail(null, 1));
}

/// <summary>
/// What: disposing a measured scope adds its elapsed time to the step.
/// </summary>
[Test]
public void MeasureDetail_AddsTheElapsedOnDispose()
{
HotReloadRunTiming timing = new HotReloadRunTiming();

using (timing.MeasureDetail("plan"))
{
}

Assert.That(timing.Details.Count, Is.EqualTo(1));
Assert.That(timing.Details[0].Key, Is.EqualTo("plan"));
Assert.That(timing.Details[0].Value, Is.GreaterThanOrEqualTo(0));
}

/// <summary>
/// What: a run that measured no step reports no steps.
/// </summary>
[Test]
public void Details_WithoutAnyStep_IsEmpty()
{
HotReloadRunTiming timing = new HotReloadRunTiming();

Assert.That(timing.Details, Is.Empty);
}
}
}
79 changes: 79 additions & 0 deletions Assets/Tests/Editor/HotReload/HotReloadTimingDetailPayloadTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System.Collections.Generic;

using NUnit.Framework;

using io.github.hatayama.UnityCliLoop.FirstPartyTools;

namespace io.github.hatayama.UnityCliLoop.Tests.Editor.HotReload
{
/// <summary>
/// Tests the timing detail entry that breaks down the time outside an apply run's phases.
/// </summary>
public sealed class HotReloadTimingDetailPayloadTests
{
/// <summary>
/// What: the entry carries each phase, the steps in order, and the part of the time outside
/// the phases that no step covers.
/// </summary>
[Test]
public void Build_ReportsThePhasesTheStepsAndTheUnaccountedRest()
{
HotReloadTimingBreakdown breakdown = new HotReloadTimingBreakdown(100, 50, 10, 1000);
List<KeyValuePair<string, long>> details = new List<KeyValuePair<string, long>>
{
new KeyValuePair<string, long>("plan", 300),
new KeyValuePair<string, long>("sibling_detect", 400),
};

HotReloadTimingDetailPayload payload = HotReloadTimingDetailPayload.Build(breakdown, details, 2);

Assert.That(payload.TotalMs, Is.EqualTo(1000));
Assert.That(payload.AnalysisMs, Is.EqualTo(100));
Assert.That(payload.ShimCompileMs, Is.EqualTo(50));
Assert.That(payload.PatchMs, Is.EqualTo(10));
Assert.That(payload.OtherMs, Is.EqualTo(840));
Assert.That(payload.UnaccountedMs, Is.EqualTo(140));
Assert.That(payload.GroupCount, Is.EqualTo(2));
Assert.That(payload.Steps.Count, Is.EqualTo(2));
Assert.That(payload.Steps[0].Step, Is.EqualTo("plan"));
Assert.That(payload.Steps[0].Ms, Is.EqualTo(300));
Assert.That(payload.Steps[1].Step, Is.EqualTo("sibling_detect"));
Assert.That(payload.Steps[1].Ms, Is.EqualTo(400));
}

/// <summary>
/// What: steps that add up to more than the time outside the phases report a negative
/// unaccounted time as it is, because that is the sign that a step overlaps a phase.
/// </summary>
[Test]
public void Build_StepsOverlappingAPhase_ReportsANegativeUnaccounted()
{
HotReloadTimingBreakdown breakdown = new HotReloadTimingBreakdown(100, 50, 10, 1000);
List<KeyValuePair<string, long>> details = new List<KeyValuePair<string, long>>
{
new KeyValuePair<string, long>("plan", 900),
};

HotReloadTimingDetailPayload payload = HotReloadTimingDetailPayload.Build(breakdown, details, 1);

Assert.That(payload.UnaccountedMs, Is.EqualTo(-60));
}

/// <summary>
/// What: a run that measured no step leaves all of the time outside the phases unaccounted.
/// </summary>
[Test]
public void Build_WithoutSteps_ReportsOtherAsUnaccounted()
{
HotReloadTimingBreakdown breakdown = new HotReloadTimingBreakdown(100, 50, 10, 1000);

HotReloadTimingDetailPayload payload = HotReloadTimingDetailPayload.Build(
breakdown,
new List<KeyValuePair<string, long>>(),
0);

Assert.That(payload.UnaccountedMs, Is.EqualTo(payload.OtherMs));
Assert.That(payload.Steps, Is.Empty);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Collections.Generic;

namespace io.github.hatayama.UnityCliLoop.FirstPartyTools
{
/// <summary>
/// Lists that a group processor derives from the files of one group.
/// </summary>
internal static class HotReloadGroupFileLists
{
// Why a file that declares a new type never counts as enum-only: its artifact is prepared
// against the whole group, and leaving its owner out would drop it from the commit.
internal static List<HotReloadLeaveOutFile> DescribeLeaveOutFiles(IReadOnlyList<HotReloadGroupFile> files)
{
List<HotReloadLeaveOutFile> leaveOutFiles = new List<HotReloadLeaveOutFile>(files.Count);
foreach (HotReloadGroupFile file in files)
{
leaveOutFiles.Add(new HotReloadLeaveOutFile(
file.ProjectRelativePath,
file.IsDefaultSelected,
file.DeclaresIntroducedType || file.DeclaresRefusedIntroducedType));
}

return leaveOutFiles;
}

internal static List<string> CollectProjectRelativePaths(IReadOnlyList<HotReloadGroupFile> files)
{
List<string> projectRelativePaths = new List<string>(files.Count);
foreach (HotReloadGroupFile file in files)
{
projectRelativePaths.Add(file.ProjectRelativePath);
}

return projectRelativePaths;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading