feat(claude-do): merge [P0-2] Timing-Hook für Hub-Invokes und Island-DB-Pfad
ClaudeDo-Task: a96c2c16-62e0-48f2-b80d-d98b113c7583
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
using System.Text.Json;
|
||||
using ClaudeDo.Ui.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace ClaudeDo.Ui.Tests.Services;
|
||||
|
||||
public class OperationTimingTests
|
||||
{
|
||||
[Fact]
|
||||
public void Record_AppendsOneWellFormedNdjsonLinePerOperation()
|
||||
{
|
||||
var dir = Path.Combine(Path.GetTempPath(), "claudedo_optiming_" + Guid.NewGuid().ToString("N"));
|
||||
var path = Path.Combine(dir, "operation-timing.ndjson");
|
||||
var sink = new OperationTiming(path);
|
||||
|
||||
try
|
||||
{
|
||||
sink.Record("hub", "RunNow", TimeSpan.FromMilliseconds(42), ok: true);
|
||||
sink.Record("db", "TasksIsland.LoadForList", TimeSpan.FromMilliseconds(7), ok: false);
|
||||
|
||||
var lines = File.ReadAllLines(path);
|
||||
Assert.Equal(2, lines.Length);
|
||||
|
||||
using var doc1 = JsonDocument.Parse(lines[0]);
|
||||
var root1 = doc1.RootElement;
|
||||
Assert.Equal("hub", root1.GetProperty("kind").GetString());
|
||||
Assert.Equal("RunNow", root1.GetProperty("op").GetString());
|
||||
Assert.Equal(42, root1.GetProperty("ms").GetInt64());
|
||||
Assert.True(root1.GetProperty("ok").GetBoolean());
|
||||
Assert.True(root1.TryGetProperty("ts", out _));
|
||||
|
||||
using var doc2 = JsonDocument.Parse(lines[1]);
|
||||
var root2 = doc2.RootElement;
|
||||
Assert.Equal("db", root2.GetProperty("kind").GetString());
|
||||
Assert.Equal("TasksIsland.LoadForList", root2.GetProperty("op").GetString());
|
||||
Assert.Equal(7, root2.GetProperty("ms").GetInt64());
|
||||
Assert.False(root2.GetProperty("ok").GetBoolean());
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (Directory.Exists(dir)) Directory.Delete(dir, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Record_SwallowsWriteFailureInsteadOfThrowing()
|
||||
{
|
||||
// A plain file sitting where the sink expects a directory makes Directory.CreateDirectory
|
||||
// throw -- standing in for the disk-full/locked-file/no-permission failures this sink
|
||||
// must survive without disturbing the caller.
|
||||
var root = Path.Combine(Path.GetTempPath(), "claudedo_optiming_invalid_" + Guid.NewGuid().ToString("N"));
|
||||
Directory.CreateDirectory(root);
|
||||
var blockingFile = Path.Combine(root, "not-a-directory");
|
||||
File.WriteAllText(blockingFile, "");
|
||||
var targetPath = Path.Combine(blockingFile, "timing.ndjson");
|
||||
var sink = new OperationTiming(targetPath);
|
||||
|
||||
try
|
||||
{
|
||||
var exception = Record.Exception(() => sink.Record("hub", "RunNow", TimeSpan.FromMilliseconds(1), ok: true));
|
||||
|
||||
Assert.Null(exception);
|
||||
Assert.False(File.Exists(targetPath));
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(root, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user