Skip to content
This repository was archived by the owner on Jul 30, 2024. It is now read-only.

Commit 61dc5b4

Browse files
committed
Fix logging statements with incorrect number of parameters (#609)
Address NuGet/NuGetGallery#6618
1 parent dd6949b commit 61dc5b4

2 files changed

Lines changed: 131 additions & 4 deletions

File tree

src/Validation.Common.Job/Storage/ValidatorStateService.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ public async Task<ValidatorStatus> TryAddValidatorStatusAsync(IValidationRequest
142142
_logger.LogWarning(
143143
Error.ValidatorStateServiceFailedToAddStatus,
144144
"Failed to add validation status for {ValidationId} ({PackageId} {PackageVersion}) as a record already exists",
145+
request.ValidationId,
145146
request.PackageId,
146147
request.PackageVersion);
147148

@@ -169,6 +170,7 @@ public async Task<ValidatorStatus> TryUpdateValidationStatusAsync(IValidationReq
169170
_logger.LogWarning(
170171
Error.ValidatorStateServiceFailedToUpdateStatus,
171172
"Failed to save validation status for {ValidationId} ({PackageId} {PackageVersion}) as the current status is stale",
173+
request.ValidationId,
172174
request.PackageId,
173175
request.PackageVersion);
174176

tests/NuGet.Services.Validation.Orchestrator.Tests/ValidatorStateServiceFacts.cs

Lines changed: 129 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,20 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Data;
67
using System.Data.Entity;
8+
using System.Data.Entity.Infrastructure;
9+
using System.Data.SqlClient;
710
using System.Linq;
11+
using System.Reflection;
812
using System.Threading.Tasks;
913
using Microsoft.Extensions.Logging;
1014
using Moq;
1115
using NuGet.Jobs.Validation;
1216
using NuGet.Jobs.Validation.Storage;
1317
using Tests.ContextHelpers;
1418
using Xunit;
19+
using Xunit.Abstractions;
1520

1621
namespace NuGet.Services.Validation
1722
{
@@ -50,6 +55,10 @@ class BValidator : IValidator
5055

5156
public class TheGetStatusMethod : FactsBase
5257
{
58+
public TheGetStatusMethod(ITestOutputHelper output) : base(output)
59+
{
60+
}
61+
5362
[Fact]
5463
public async Task GetStatusReturnsNotStartedIfNoPersistedStatus()
5564
{
@@ -170,6 +179,10 @@ public async Task GetStatusThrowsOnInvalidValidatorName()
170179

171180
public class TheIsRevalidationRequestMethod : FactsBase
172181
{
182+
public TheIsRevalidationRequestMethod(ITestOutputHelper output) : base(output)
183+
{
184+
}
185+
173186
[Fact]
174187
public async Task ReturnsFalseIfPackageHasNeverBeenValidated()
175188
{
@@ -318,6 +331,10 @@ public async Task ReturnsTrueIfPackageHasBeenValidatedByMultipleValidatorsAndCur
318331

319332
public class TheAddStatusAsyncMethod : FactsBase
320333
{
334+
public TheAddStatusAsyncMethod(ITestOutputHelper output) : base(output)
335+
{
336+
}
337+
321338
[Fact]
322339
public async Task AddStatusAsyncThrowsIfValidatorNameIsWrong()
323340
{
@@ -372,6 +389,10 @@ public async Task AddStatusAsyncMethodPersistsStatus(ValidationStatus status)
372389

373390
public class TheSaveStatusAsyncMethod : FactsBase
374391
{
392+
public TheSaveStatusAsyncMethod(ITestOutputHelper output) : base(output)
393+
{
394+
}
395+
375396
[Fact]
376397
public async Task SaveStatusAsyncThrowsIfValidatorNameIsWrong()
377398
{
@@ -414,13 +435,42 @@ public async Task SaveStatusAsyncMethodPersistsStatus(ValidationStatus status)
414435

415436
public class TheTryAddValidatorStatusAsyncMethod : FactsBase
416437
{
438+
public TheTryAddValidatorStatusAsyncMethod(ITestOutputHelper output) : base(output)
439+
{
440+
}
441+
417442
private ValidatorStatus NewStatus => new ValidatorStatus
418443
{
419444
ValidationId = ValidationId,
420445
PackageKey = PackageKey,
421446
ValidatorName = nameof(AValidator),
422447
};
423448

449+
[Fact]
450+
public async Task HandlesUniqueConstraintViolationGracefully()
451+
{
452+
// Arrange
453+
var exception = new DbUpdateException(
454+
message: "Fail!",
455+
innerException: CreateSqlException(2627, "No can do, friend."));
456+
_validationContext
457+
.Setup(x => x.SaveChangesAsync())
458+
.ThrowsAsync(exception);
459+
460+
_validationContext.Mock(validatorStatusesMock: new Mock<IDbSet<ValidatorStatus>>());
461+
var status = NewStatus;
462+
463+
// Act
464+
var result = await _target.TryAddValidatorStatusAsync(
465+
_validationRequest.Object,
466+
status,
467+
ValidationStatus.Succeeded);
468+
469+
// Assert
470+
Assert.Same(status, result);
471+
_validationContext.Verify(x => x.ValidatorStatuses, Times.Exactly(2));
472+
}
473+
424474
[Fact]
425475
public async Task PersistsStatus()
426476
{
@@ -453,6 +503,10 @@ public async Task PersistsStatus()
453503

454504
public class TheTryUpdateValidationStatusAsyncMethod : FactsBase
455505
{
506+
public TheTryUpdateValidationStatusAsyncMethod(ITestOutputHelper output) : base(output)
507+
{
508+
}
509+
456510
private ValidatorStatus ExistingStatus => new ValidatorStatus
457511
{
458512
ValidationId = ValidationId,
@@ -461,6 +515,30 @@ public class TheTryUpdateValidationStatusAsyncMethod : FactsBase
461515
State = ValidationStatus.NotStarted,
462516
};
463517

518+
[Fact]
519+
public async Task HandlesUniqueConstraintViolationGracefully()
520+
{
521+
// Arrange
522+
var exception = new DbUpdateConcurrencyException("Fail!");
523+
_validationContext
524+
.Setup(x => x.SaveChangesAsync())
525+
.ThrowsAsync(exception);
526+
527+
_validationContext.Mock(validatorStatusesMock: new Mock<IDbSet<ValidatorStatus>>());
528+
var status = ExistingStatus;
529+
_validationContext.Object.ValidatorStatuses.Add(status);
530+
531+
// Act
532+
var result = await _target.TryUpdateValidationStatusAsync(
533+
_validationRequest.Object,
534+
status,
535+
ValidationStatus.Succeeded);
536+
537+
// Assert
538+
Assert.Same(status, result);
539+
_validationContext.Verify(x => x.ValidatorStatuses, Times.Exactly(2));
540+
}
541+
464542
[Fact]
465543
public async Task PersistsStatus()
466544
{
@@ -484,15 +562,17 @@ public async Task PersistsStatus()
484562

485563
public abstract class FactsBase
486564
{
565+
protected readonly ITestOutputHelper _output;
487566
protected readonly Mock<IValidationEntitiesContext> _validationContext;
488-
protected readonly Mock<ILogger<ValidatorStateService>> _logger;
567+
protected readonly ILogger<ValidatorStateService> _logger;
489568
protected readonly Mock<IValidationRequest> _validationRequest;
490569
protected readonly ValidatorStateService _target;
491570

492-
public FactsBase()
571+
public FactsBase(ITestOutputHelper output)
493572
{
573+
_output = output ?? throw new ArgumentNullException(nameof(output));
494574
_validationContext = new Mock<IValidationEntitiesContext>();
495-
_logger = new Mock<ILogger<ValidatorStateService>>();
575+
_logger = new LoggerFactory().AddXunit(_output).CreateLogger<ValidatorStateService>();
496576

497577
_validationRequest = new Mock<IValidationRequest>();
498578
_validationRequest.Setup(x => x.NupkgUrl).Returns(NupkgUrl);
@@ -508,7 +588,52 @@ protected ValidatorStateService CreateValidatorStateService(string validatorName
508588
=> new ValidatorStateService(
509589
_validationContext.Object,
510590
validatorName,
511-
_logger.Object);
591+
_logger);
592+
593+
/// <summary>
594+
/// Source: http://blog.gauffin.org/2014/08/how-to-create-a-sqlexception/
595+
/// </summary>
596+
protected SqlException CreateSqlException(int number, string message)
597+
{
598+
var collectionConstructor = typeof(SqlErrorCollection)
599+
.GetConstructor(
600+
bindingAttr: BindingFlags.NonPublic | BindingFlags.Instance,
601+
binder: null,
602+
types: new Type[0],
603+
modifiers: null);
604+
var addMethod = typeof(SqlErrorCollection).GetMethod("Add", BindingFlags.NonPublic | BindingFlags.Instance);
605+
var errorCollection = (SqlErrorCollection)collectionConstructor.Invoke(null);
606+
607+
var errorConstructor = typeof(SqlError).GetConstructor(
608+
bindingAttr: BindingFlags.NonPublic | BindingFlags.Instance,
609+
binder: null,
610+
types: new[]
611+
{
612+
typeof (int), typeof (byte), typeof (byte), typeof (string), typeof(string), typeof (string),
613+
typeof (int), typeof (uint)
614+
},
615+
modifiers: null);
616+
var error = errorConstructor.Invoke(new object[]
617+
{
618+
number,
619+
(byte)0,
620+
(byte)0,
621+
"server",
622+
"errMsg",
623+
"procedure",
624+
100,
625+
(uint)0
626+
});
627+
628+
addMethod.Invoke(errorCollection, new[] { error });
629+
630+
var constructor = typeof(SqlException).GetConstructor(
631+
bindingAttr: BindingFlags.NonPublic | BindingFlags.Instance,
632+
binder: null,
633+
types: new[] { typeof(string), typeof(SqlErrorCollection), typeof(Exception), typeof(Guid) },
634+
modifiers: null);
635+
return (SqlException)constructor.Invoke(new object[] { message, errorCollection, null, Guid.NewGuid() });
636+
}
512637
}
513638
}
514639
}

0 commit comments

Comments
 (0)