1- // Copyright (c) .NET Foundation. All rights reserved.
1+ // Copyright (c) .NET Foundation. All rights reserved.
22// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33
44using System ;
@@ -35,7 +35,9 @@ public void TransformRawLogLine(string input, string expectedOutput)
3535 var collector = new ChinaStatsCollector (
3636 Mock . Of < ILogSource > ( ) ,
3737 Mock . Of < ILogDestination > ( ) ,
38- Mock . Of < ILogger < ChinaStatsCollector > > ( ) ) ;
38+ Mock . Of < ILogger < ChinaStatsCollector > > ( ) ,
39+ writeHeader : true ,
40+ addSourceFilenameColumn : false ) ;
3941
4042 var transformedInput = collector . TransformRawLogLine ( input ) ;
4143 string output = transformedInput == null ? null : transformedInput . ToString ( ) ;
@@ -51,7 +53,9 @@ public void CdnLogEntryParserIntegration(string input)
5153 var collector = new ChinaStatsCollector (
5254 Mock . Of < ILogSource > ( ) ,
5355 Mock . Of < ILogDestination > ( ) ,
54- Mock . Of < ILogger < ChinaStatsCollector > > ( ) ) ;
56+ Mock . Of < ILogger < ChinaStatsCollector > > ( ) ,
57+ writeHeader : true ,
58+ addSourceFilenameColumn : false ) ;
5559
5660 var transformedInput = collector . TransformRawLogLine ( input ) ;
5761 if ( transformedInput == null )
@@ -74,7 +78,9 @@ public void SkipsMalformedTimestamps()
7478 var collector = new ChinaStatsCollector (
7579 Mock . Of < ILogSource > ( ) ,
7680 Mock . Of < ILogDestination > ( ) ,
77- Mock . Of < ILogger < ChinaStatsCollector > > ( ) ) ;
81+ Mock . Of < ILogger < ChinaStatsCollector > > ( ) ,
82+ writeHeader : true ,
83+ addSourceFilenameColumn : false ) ;
7884
7985 OutputLogLine transformedInput = null ;
8086
@@ -121,54 +127,146 @@ public void SkipsMalformedTimestamps()
121127 public async Task SkipsLinesWithMalformedColumns ( string data , int expectedOutputLines )
122128 {
123129 const string header = "c-ip, timestamp, cs-method, cs-uri-stem, http-ver, sc-status, sc-bytes, c-referer, c-user-agent, rs-duration(ms), hit-miss, s-ip\n " ;
124- var sourceUri = new Uri ( "https://example.com/log1" ) ;
130+ Mock < ILogSource > sourceMock = SetupSource ( header + data ) ;
125131
126- var sourceMock = new Mock < ILogSource > ( ) ;
127- sourceMock
128- . Setup ( s => s . GetFilesAsync ( It . IsAny < int > ( ) , It . IsAny < CancellationToken > ( ) , It . IsAny < string > ( ) ) )
129- . ReturnsAsync ( ( IEnumerable < Uri > ) new List < Uri > { sourceUri } ) ;
132+ var writeSucceeded = false ;
133+ var outputStream = new MemoryStream ( ) ;
134+ Mock < ILogDestination > destinationMock = SetupDestination ( outputStream , ( ) => writeSucceeded = true ) ;
130135
131- sourceMock
132- . Setup ( s => s . TakeLockAsync ( sourceUri , It . IsAny < CancellationToken > ( ) ) )
133- . ReturnsAsync ( new AzureBlobLockResult ( new Microsoft . WindowsAzure . Storage . Blob . CloudBlob ( sourceUri ) , true , "foo" , CancellationToken . None ) ) ;
136+ var collector = new ChinaStatsCollector (
137+ sourceMock . Object ,
138+ destinationMock . Object ,
139+ Mock . Of < ILogger < ChinaStatsCollector > > ( ) ,
140+ writeHeader : true ,
141+ addSourceFilenameColumn : false ) ;
134142
135- sourceMock
136- . Setup ( s => s . OpenReadAsync ( sourceUri , It . IsAny < ContentType > ( ) , It . IsAny < CancellationToken > ( ) ) )
137- . ReturnsAsync ( ( ) => new MemoryStream ( Encoding . UTF8 . GetBytes ( header + data ) ) ) ;
143+ await collector . TryProcessAsync (
144+ maxFileCount : 10 ,
145+ fileNameTransform : s => s ,
146+ sourceContentType : ContentType . Text ,
147+ destinationContentType : ContentType . Text ,
148+ CancellationToken . None ) ;
138149
139- var destinationMock = new Mock < ILogDestination > ( ) ;
150+ string [ ] outputLines = null ;
151+
152+ outputLines = GetStreamLines ( outputStream ) ;
153+
154+ Assert . True ( writeSucceeded ) ;
155+ Assert . NotEmpty ( outputLines ) ;
156+ Assert . Equal ( "#Fields: timestamp time-taken c-ip filesize s-ip s-port sc-status sc-bytes cs-method cs-uri-stem - rs-duration rs-bytes c-referrer c-user-agent customer-id x-ec_custom-1" , outputLines [ 0 ] ) ;
157+ Assert . True ( expectedOutputLines <= outputLines . Length - 1 ) ; // excluding header
158+ }
159+
160+ [ Fact ]
161+ public async Task DoesNotWriteHeaderIfConfigured ( )
162+ {
163+ const string header = "c-ip, timestamp, cs-method, cs-uri-stem, http-ver, sc-status, sc-bytes, c-referer, c-user-agent, rs-duration(ms), hit-miss, s-ip\n " ;
164+ const string data = "1.2.3.4,4/6/2019 4:00:20 PM +00:00,GET,\" /v3-flatcontainer/microsoft.codeanalysis.common/1.2.2/microsoft.codeanalysis.common.1.2.2.nupkg\" ,HTTPS,200,2044843,\" NULL\" ,\" NuGet VS VSIX/4.7.0 (Microsoft Windows NT 10.0.17134.0, VS Enterprise/15.0)\" ,796,MISS,4.3.2.1" ;
165+
166+ Mock < ILogSource > sourceMock = SetupSource ( header + data ) ;
167+ var writeSucceeded = false ;
140168 var outputStream = new MemoryStream ( ) ;
169+ Mock < ILogDestination > destinationMock = SetupDestination ( outputStream , ( ) => writeSucceeded = true ) ;
170+
171+ var collector = new ChinaStatsCollector (
172+ sourceMock . Object ,
173+ destinationMock . Object ,
174+ Mock . Of < ILogger < ChinaStatsCollector > > ( ) ,
175+ writeHeader : false ,
176+ addSourceFilenameColumn : false ) ;
177+
178+ await collector . TryProcessAsync (
179+ maxFileCount : 10 ,
180+ fileNameTransform : s => s ,
181+ sourceContentType : ContentType . Text ,
182+ destinationContentType : ContentType . Text ,
183+ CancellationToken . None ) ;
184+
185+ string [ ] outputLines = null ;
186+
187+ outputLines = GetStreamLines ( outputStream ) ;
188+ Assert . True ( writeSucceeded ) ;
189+ Assert . Single ( outputLines ) ;
190+ Assert . False ( outputLines [ 0 ] . StartsWith ( "#Fields" ) ) ;
191+ }
192+
193+ [ Fact ]
194+ public async Task WritesSourceFilenameColumn ( )
195+ {
196+ const string header = "c-ip, timestamp, cs-method, cs-uri-stem, http-ver, sc-status, sc-bytes, c-referer, c-user-agent, rs-duration(ms), hit-miss, s-ip\n " ;
197+ const string data = "1.2.3.4,4/6/2019 4:00:20 PM +00:00,GET,\" /v3-flatcontainer/microsoft.codeanalysis.common/1.2.2/microsoft.codeanalysis.common.1.2.2.nupkg\" ,HTTPS,200,2044843,\" NULL\" ,\" NuGet VS VSIX/4.7.0 (Microsoft Windows NT 10.0.17134.0, VS Enterprise/15.0)\" ,796,MISS,4.3.2.1" ;
198+
199+ Mock < ILogSource > sourceMock = SetupSource ( header + data ) ;
141200 var writeSucceeded = false ;
201+ var outputStream = new MemoryStream ( ) ;
202+ Mock < ILogDestination > destinationMock = SetupDestination ( outputStream , ( ) => writeSucceeded = true ) ;
203+
204+ var collector = new ChinaStatsCollector (
205+ sourceMock . Object ,
206+ destinationMock . Object ,
207+ Mock . Of < ILogger < ChinaStatsCollector > > ( ) ,
208+ writeHeader : true ,
209+ addSourceFilenameColumn : true ) ;
210+
211+ await collector . TryProcessAsync (
212+ maxFileCount : 10 ,
213+ fileNameTransform : s => s ,
214+ sourceContentType : ContentType . Text ,
215+ destinationContentType : ContentType . Text ,
216+ CancellationToken . None ) ;
217+
218+ string [ ] outputLines = null ;
219+
220+ outputLines = GetStreamLines ( outputStream ) ;
221+ Assert . True ( writeSucceeded ) ;
222+ Assert . Equal ( 2 , outputLines . Length ) ;
223+ Assert . EndsWith ( "sourceFilename" , outputLines [ 0 ] ) ;
224+ Assert . EndsWith ( "log1" , outputLines [ 1 ] ) ;
225+ }
226+
227+ private static Mock < ILogDestination > SetupDestination ( MemoryStream outputStream , Action onSuccess )
228+ {
229+ var destinationMock = new Mock < ILogDestination > ( ) ;
142230 destinationMock
143231 . Setup ( d => d . TryWriteAsync ( It . IsAny < Stream > ( ) , It . IsAny < Action < Stream , Stream > > ( ) , It . IsAny < string > ( ) , It . IsAny < ContentType > ( ) , It . IsAny < CancellationToken > ( ) ) )
144232 . ReturnsAsync ( ( Stream inputStream , Action < Stream , Stream > writeAction , string destinationFileName , ContentType destinationContentType , CancellationToken token ) =>
145233 {
146234 try
147235 {
148236 writeAction ( inputStream , outputStream ) ;
149- writeSucceeded = true ;
237+ onSuccess ( ) ;
150238 }
151239 catch ( Exception ex )
152240 {
153241 return new AsyncOperationResult ( false , ex ) ;
154242 }
155243 return new AsyncOperationResult ( true , null ) ;
156244 } ) ;
245+ return destinationMock ;
246+ }
157247
158- var collector = new ChinaStatsCollector (
159- sourceMock . Object ,
160- destinationMock . Object ,
161- Mock . Of < ILogger < ChinaStatsCollector > > ( ) ) ;
248+ private static Mock < ILogSource > SetupSource ( string content )
249+ {
250+ var sourceUri = new Uri ( "https://example.com/log1" ) ;
162251
163- await collector . TryProcessAsync (
164- maxFileCount : 10 ,
165- fileNameTransform : s => s ,
166- sourceContentType : ContentType . Text ,
167- destinationContentType : ContentType . Text ,
168- CancellationToken . None ) ;
252+ var sourceMock = new Mock < ILogSource > ( ) ;
253+ sourceMock
254+ . Setup ( s => s . GetFilesAsync ( It . IsAny < int > ( ) , It . IsAny < CancellationToken > ( ) , It . IsAny < string > ( ) ) )
255+ . ReturnsAsync ( ( IEnumerable < Uri > ) new List < Uri > { sourceUri } ) ;
169256
170- string [ ] outputLines = null ;
257+ sourceMock
258+ . Setup ( s => s . TakeLockAsync ( sourceUri , It . IsAny < CancellationToken > ( ) ) )
259+ . ReturnsAsync ( new AzureBlobLockResult ( new Microsoft . WindowsAzure . Storage . Blob . CloudBlob ( sourceUri ) , true , "foo" , CancellationToken . None ) ) ;
171260
261+ sourceMock
262+ . Setup ( s => s . OpenReadAsync ( sourceUri , It . IsAny < ContentType > ( ) , It . IsAny < CancellationToken > ( ) ) )
263+ . ReturnsAsync ( ( ) => new MemoryStream ( Encoding . UTF8 . GetBytes ( content ) ) ) ;
264+ return sourceMock ;
265+ }
266+
267+ private static string [ ] GetStreamLines ( MemoryStream outputStream )
268+ {
269+ string [ ] outputLines ;
172270 // need to reopen closed stream
173271 var outputBuffer = outputStream . ToArray ( ) ;
174272 outputStream = new MemoryStream ( outputBuffer ) ;
@@ -177,11 +275,7 @@ await collector.TryProcessAsync(
177275 outputLines = streamReader . ReadToEnd ( ) . Split ( new [ ] { '\r ' , '\n ' } , StringSplitOptions . RemoveEmptyEntries ) ;
178276 }
179277
180- Assert . True ( writeSucceeded ) ;
181- Assert . NotEmpty ( outputLines ) ;
182- Assert . Equal ( "#Fields: timestamp time-taken c-ip filesize s-ip s-port sc-status sc-bytes cs-method cs-uri-stem - rs-duration rs-bytes c-referrer c-user-agent customer-id x-ec_custom-1" , outputLines [ 0 ] ) ;
183- Assert . True ( expectedOutputLines <= outputLines . Length - 1 ) ; // excluding header
278+ return outputLines ;
184279 }
185280 }
186281}
187-
0 commit comments