-
Notifications
You must be signed in to change notification settings - Fork 117
/
FileSinkTests.cs
259 lines (210 loc) · 8.01 KB
/
FileSinkTests.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
using System.IO.Compression;
using System.Text;
using Xunit;
using Serilog.Formatting.Json;
using Serilog.Sinks.File.Tests.Support;
using Serilog.Tests.Support;
#pragma warning disable 618
namespace Serilog.Sinks.File.Tests;
public class FileSinkTests
{
[Fact]
public void FileIsWrittenIfNonexistent()
{
using var tmp = TempFolder.ForCaller();
var nonexistent = tmp.AllocateFilename("txt");
var evt = Some.LogEvent("Hello, world!");
using (var sink = new FileSink(nonexistent, new JsonFormatter(), null))
{
sink.Emit(evt);
}
var lines = System.IO.File.ReadAllLines(nonexistent);
Assert.Contains("Hello, world!", lines[0]);
}
[Fact]
public void FileIsAppendedToWhenAlreadyCreated()
{
using var tmp = TempFolder.ForCaller();
var path = tmp.AllocateFilename("txt");
var evt = Some.LogEvent("Hello, world!");
using (var sink = new FileSink(path, new JsonFormatter(), null))
{
sink.Emit(evt);
}
using (var sink = new FileSink(path, new JsonFormatter(), null))
{
sink.Emit(evt);
}
var lines = System.IO.File.ReadAllLines(path);
Assert.Contains("Hello, world!", lines[0]);
Assert.Contains("Hello, world!", lines[1]);
}
[Fact]
public void WhenLimitIsSpecifiedFileSizeIsRestricted()
{
const int maxBytes = 5000;
const int eventsToLimit = 10;
using var tmp = TempFolder.ForCaller();
var path = tmp.AllocateFilename("txt");
var evt = Some.LogEvent(new string('n', maxBytes / eventsToLimit));
using (var sink = new FileSink(path, new JsonFormatter(), maxBytes))
{
for (var i = 0; i < eventsToLimit * 2; i++)
{
sink.Emit(evt);
}
}
var size = new FileInfo(path).Length;
Assert.True(size > maxBytes);
Assert.True(size < maxBytes * 2);
}
[Fact]
public void WhenLimitIsNotSpecifiedFileSizeIsNotRestricted()
{
const int maxBytes = 5000;
const int eventsToLimit = 10;
using var tmp = TempFolder.ForCaller();
var path = tmp.AllocateFilename("txt");
var evt = Some.LogEvent(new string('n', maxBytes / eventsToLimit));
using (var sink = new FileSink(path, new JsonFormatter(), null))
{
for (var i = 0; i < eventsToLimit * 2; i++)
{
sink.Emit(evt);
}
}
var size = new FileInfo(path).Length;
Assert.True(size > maxBytes * 2);
}
[Fact]
public void WhenLimitIsSpecifiedAndEncodingHasPreambleDataIsCorrectlyAppendedToFileSink()
{
long? maxBytes = 5000;
var encoding = Encoding.UTF8;
Assert.True(encoding.GetPreamble().Length > 0);
WriteTwoEventsAndCheckOutputFileLength(maxBytes, encoding);
}
[Fact]
public void WhenLimitIsNotSpecifiedAndEncodingHasPreambleDataIsCorrectlyAppendedToFileSink()
{
var encoding = Encoding.UTF8;
Assert.True(encoding.GetPreamble().Length > 0);
WriteTwoEventsAndCheckOutputFileLength(null, encoding);
}
[Fact]
public void WhenLimitIsSpecifiedAndEncodingHasNoPreambleDataIsCorrectlyAppendedToFileSink()
{
long? maxBytes = 5000;
var encoding = new UTF8Encoding(false);
Assert.Empty(encoding.GetPreamble());
WriteTwoEventsAndCheckOutputFileLength(maxBytes, encoding);
}
[Fact]
public void WhenLimitIsNotSpecifiedAndEncodingHasNoPreambleDataIsCorrectlyAppendedToFileSink()
{
var encoding = new UTF8Encoding(false);
Assert.Empty(encoding.GetPreamble());
WriteTwoEventsAndCheckOutputFileLength(null, encoding);
}
[Fact]
public void OnOpenedLifecycleHookCanWrapUnderlyingStream()
{
var gzipWrapper = new GZipHooks();
using var tmp = TempFolder.ForCaller();
var path = tmp.AllocateFilename("txt");
var evt = Some.LogEvent("Hello, world!");
using (var sink = new FileSink(path, new JsonFormatter(), null, null, false, gzipWrapper))
{
sink.Emit(evt);
sink.Emit(evt);
}
// Ensure the data was written through the wrapping GZipStream, by decompressing and comparing against
// what we wrote
List<string> lines;
using (var textStream = new MemoryStream())
{
using (var fs = System.IO.File.OpenRead(path))
using (var decompressStream = new GZipStream(fs, CompressionMode.Decompress))
{
decompressStream.CopyTo(textStream);
}
textStream.Position = 0;
lines = textStream.ReadAllLines();
}
Assert.Equal(2, lines.Count);
Assert.Contains("Hello, world!", lines[0]);
}
[Fact]
public static void OnOpenedLifecycleHookCanWriteFileHeader()
{
using var tmp = TempFolder.ForCaller();
var headerWriter = new FileHeaderWriter("This is the file header");
var path = tmp.AllocateFilename("txt");
using (new FileSink(path, new JsonFormatter(), null, new UTF8Encoding(false), false, headerWriter))
{
// Open and write header
}
using (var sink = new FileSink(path, new JsonFormatter(), null, new UTF8Encoding(false), false, headerWriter))
{
// Length check should prevent duplicate header here
sink.Emit(Some.LogEvent());
}
var lines = System.IO.File.ReadAllLines(path);
Assert.Equal(2, lines.Length);
Assert.Equal(headerWriter.Header, lines[0]);
Assert.Equal('{', lines[1][0]);
}
[Fact]
public static void OnOpenedLifecycleHookCanCaptureFilePath()
{
using var tmp = TempFolder.ForCaller();
var capturePath = new CaptureFilePathHook();
var path = tmp.AllocateFilename("txt");
using (new FileSink(path, new JsonFormatter(), null, new UTF8Encoding(false), false, capturePath))
{
// Open and capture the log file path
}
Assert.Equal(path, capturePath.Path);
}
[Fact]
public static void OnOpenedLifecycleHookCanEmptyTheFileContents()
{
using var tmp = TempFolder.ForCaller();
var emptyFileHook = new TruncateFileHook();
var path = tmp.AllocateFilename("txt");
using (var sink = new FileSink(path, new JsonFormatter(), fileSizeLimitBytes: null, encoding: new UTF8Encoding(false), buffered: false))
{
sink.Emit(Some.LogEvent());
}
using (var sink = new FileSink(path, new JsonFormatter(), fileSizeLimitBytes: null, encoding: new UTF8Encoding(false), buffered: false, hooks: emptyFileHook))
{
// Hook will clear the contents of the file before emitting the log events
sink.Emit(Some.LogEvent());
}
var lines = System.IO.File.ReadAllLines(path);
Assert.Single(lines);
Assert.Equal('{', lines[0][0]);
}
static void WriteTwoEventsAndCheckOutputFileLength(long? maxBytes, Encoding encoding)
{
using var tmp = TempFolder.ForCaller();
var path = tmp.AllocateFilename("txt");
var evt = Some.LogEvent("Irrelevant as it will be replaced by the formatter");
const string actualEventOutput = "x";
var formatter = new FixedOutputFormatter(actualEventOutput);
var eventOuputLength = encoding.GetByteCount(actualEventOutput);
using (var sink = new FileSink(path, formatter, maxBytes, encoding: encoding))
{
sink.Emit(evt);
}
var size = new FileInfo(path).Length;
Assert.Equal(encoding.GetPreamble().Length + eventOuputLength, size);
//write a second event to the same file
using (var sink = new FileSink(path, formatter, maxBytes, encoding: encoding))
{
sink.Emit(evt);
}
size = new FileInfo(path).Length;
Assert.Equal(encoding.GetPreamble().Length + eventOuputLength * 2, size);
}
}