pulumi/sdk/dotnet/Pulumi.Automation.Tests/EventLogWatcherTests.cs
Ville Penttinen 529fe8fc51
[automation/dotnet] Expose structured logging (#6572)
* [automation/dotnet] Start implementing structured event log support

* Add Events and their models

* Introduce new IStringToEnumConverter

This is intended to be used for converting a non-standard enum names
into corresponding enum values. The converter is utilized via
StringToEnumJsonConverter with OperationType and DiffKind.

* Add event-log support to up, refresh, destroy

* Update event-log tests

* Use lock instead of semaphore in EventLogWatcher

* Add ChangeSummary to PreviewResult

* Minor update

* Add doc comments to Events

* Use PropertyDiffModel in StepEventMetadataModel

* Set Events to public

* Set properties to public

* Fix PreludeEvent.Config doc comment

* Remove TODOs

* Update Pulumi.Automation.xml

* Set PULUMI_DEBUG_COMMANDs in Workspace.

* Split Events and their models to separate files

* Rename abbreviated Events

* Remove CancelEventModel

* Rename HandlesEvents test project and stack

* Update CHANGELOG_PENDING.md

* Rename abbreviated EngineEvent properties

* Implement custom exceptions

* Move event-log setup to LocalPulumiCmd

* Update comments

* Implement polling EventLogWatcher

This replaces the previous watcher which utilized FileSystemWatcher.

* Guard against onEvent throwing

* Dispose CancellationTokenSource

* WIP: try more direct error handling in EventLogWatcher

* A bit more tests

* Reformat

* Update sdk/dotnet/Pulumi.Automation.Tests/EventLogWatcherTests.cs

Co-authored-by: Ville Penttinen <villem.penttinen@gmail.com>

* Update sdk/dotnet/Pulumi.Automation/Events/EventLogWatcher.cs

Co-authored-by: Ville Penttinen <villem.penttinen@gmail.com>

* Update sdk/dotnet/Pulumi.Automation/Events/EventLogWatcher.cs

Co-authored-by: Ville Penttinen <villem.penttinen@gmail.com>

* Update sdk/dotnet/Pulumi.Automation.Tests/EventLogWatcherTests.cs

Co-authored-by: Ville Penttinen <villem.penttinen@gmail.com>

* Update sdk/dotnet/Pulumi.Automation/Events/EventLogWatcher.cs

Co-authored-by: Ville Penttinen <villem.penttinen@gmail.com>

* Update sdk/dotnet/Pulumi.Automation/Events/EventLogWatcher.cs

Co-authored-by: Ville Penttinen <villem.penttinen@gmail.com>

* Make race condition workaround more explicit

* Untabify

* Remove unnecessary using and change String to string

* Update doc comments on Events

Co-authored-by: Anton Tayanovskyy <anton@pulumi.com>
Co-authored-by: Anton Tayanovskyy <anton.tayanovskyy@gmail.com>
2021-03-30 14:57:38 -04:00

102 lines
2.8 KiB
C#

// Copyright 2016-2021, Pulumi Corporation
using System.Threading;
using System.Threading.Tasks;
using System.IO;
using System;
using Pulumi.Automation.Events;
using Xunit;
namespace Pulumi.Automation.Tests
{
public class EventLogWatcherTests
{
[Fact]
public async Task ReceivesBasicEvent()
{
using var fx = new Fixture();
await fx.Write("{}");
await fx.Watcher.Stop();
Assert.Equal(1, fx.EventCounter);
}
[Fact]
public async Task ReceivesManyBasicEvents()
{
using var fx = new Fixture();
for (var i = 0; i < 10; i++)
{
await fx.Write("{}");
}
await fx.Watcher.Stop();
Assert.Equal(10, fx.EventCounter);
}
[Fact]
public async Task PropagatesUserExceptionsToCaller()
{
using var fx = new Fixture();
fx.Action = ev =>
{
throw new MyException();
};
await fx.Write("{}");
await Assert.ThrowsAsync<MyException>(async () =>
{
await fx.Watcher.Stop();
});
}
[Fact]
public async Task PermitsUserInitiatedCancellation()
{
using var fx = new Fixture();
fx.CancellationTokenSource.Cancel();
await fx.Watcher.AwaitPollingTask();
}
private class MyException : Exception { }
private class Fixture : IDisposable
{
public int EventCounter;
public string LogFileName { get; }
public StreamWriter Writer { get; }
public EventLogWatcher Watcher { get; }
public CancellationTokenSource CancellationTokenSource { get; }
public Action<EngineEvent>? Action { get; set; }
public Fixture()
{
this.CancellationTokenSource = new CancellationTokenSource();
this.LogFileName = Path.GetTempFileName();
this.Writer = new StreamWriter(this.LogFileName);
this.Watcher = new EventLogWatcher(this.LogFileName, onEvent: ev =>
{
Interlocked.Increment(ref this.EventCounter);
this.Action?.Invoke(ev);
}, this.CancellationTokenSource.Token);
}
public async Task Write(string text)
{
await this.Writer.WriteLineAsync(text);
await this.Writer.FlushAsync();
}
public void Dispose()
{
this.Watcher.Dispose();
this.CancellationTokenSource.Dispose();
this.Writer.Dispose();
File.Delete(this.LogFileName);
}
}
}
}