Skip to content

Commit

Permalink
fix(playwrighttesting): Using dependency injection instead of BlobCli…
Browse files Browse the repository at this point in the history
…ent in TestProcessor (#46807)

* fix(playwrighttesting): Using dependency injection instead of BlobClient in TestProcessor

* update

* update

* removed previous commit

* added test for bobService

* update

* update test

* added test for sas uri.

* updated UploadBlobFile

* update

---------

Co-authored-by: guptakashish <guptakashish@microsoft.com>
  • Loading branch information
kashish2508 and guptakashish authored Nov 4, 2024
1 parent 63e086e commit 52190ed
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 39 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Text;
using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Interface;
using Azure.Storage.Blobs;
using System.Threading.Tasks;
using System.IO;

namespace Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Implementation
{
internal class BlobService:IBlobService
{
private readonly ILogger _logger;

public BlobService(ILogger? logger)
{
_logger = logger ?? new Logger();
}

public async Task UploadBufferAsync(string uri, string buffer, string fileRelativePath)
{
try
{
string cloudFilePath = GetCloudFilePath(uri, fileRelativePath);
BlobClient blobClient = new(new Uri(cloudFilePath));
byte[] bufferBytes = Encoding.UTF8.GetBytes(buffer);
await blobClient.UploadAsync(new BinaryData(bufferBytes), overwrite: true).ConfigureAwait(false);
_logger.Info($"Uploaded buffer to {fileRelativePath}");
}
catch (Exception ex)
{
_logger.Error($"Failed to upload buffer: {ex}");
}
}
public void UploadBlobFile(string uri, string fileRelativePath, string filePath)
{
string cloudFilePath = GetCloudFilePath(uri, fileRelativePath);
BlobClient blobClient = new(new Uri(cloudFilePath));
blobClient.Upload(filePath, overwrite: true);
_logger.Info($"Uploaded file {filePath} to {fileRelativePath}");
}
public string GetCloudFilePath(string uri, string fileRelativePath)
{
string[] parts = uri.Split(new string[] { ReporterConstants.s_sASUriSeparator }, StringSplitOptions.None);
string containerUri = parts[0];
string sasToken = parts.Length > 1 ? parts[1] : string.Empty;

return $"{containerUri}/{fileRelativePath}?{sasToken}";
}
public string? GetCloudFileName(string filePath, string testExecutionId)
{
var fileName = Path.GetFileName(filePath);
if (fileName == null)
{
return null;
}
return $"{testExecutionId}/{fileName}"; // TODO check if we need to add {Guid.NewGuid()} for file with same name
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Threading.Tasks;
namespace Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Interface
{
internal interface IBlobService
{
/// <summary>
///
/// </summary>
/// <param name="uri"></param>
/// <param name="buffer"></param>
/// <param name="fileRelativePath"></param>
/// <returns>A <see cref="Task"/> representing the result of the asynchronous operation.</returns>
Task UploadBufferAsync(string uri, string buffer, string fileRelativePath);
string GetCloudFilePath(string uri, string fileRelativePath);
void UploadBlobFile(string uri, string fileRelativePath, string filePath);
public string? GetCloudFileName(string filePath, string testExecutionId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.IO;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Implementation;
using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Interface;
using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Model;
Expand All @@ -28,6 +29,7 @@ internal class TestProcessor : ITestProcessor
private readonly IConsoleWriter _consoleWriter;
private readonly CIInfo _cIInfo;
private readonly CloudRunMetadata _cloudRunMetadata;
private readonly IBlobService _blobService;

// Test Metadata
internal int TotalTestCount { get; set; } = 0;
Expand All @@ -42,7 +44,7 @@ internal class TestProcessor : ITestProcessor
internal TestRunShardDto? _testRunShard;
internal TestResultsUri? _testResultsSasUri;

public TestProcessor(CloudRunMetadata cloudRunMetadata, CIInfo cIInfo, ILogger? logger = null, IDataProcessor? dataProcessor = null, ICloudRunErrorParser? cloudRunErrorParser = null, IServiceClient? serviceClient = null, IConsoleWriter? consoleWriter = null)
public TestProcessor(CloudRunMetadata cloudRunMetadata, CIInfo cIInfo, ILogger? logger = null, IDataProcessor? dataProcessor = null, ICloudRunErrorParser? cloudRunErrorParser = null, IServiceClient? serviceClient = null, IConsoleWriter? consoleWriter = null, IBlobService? blobService = null)
{
_cloudRunMetadata = cloudRunMetadata;
_cIInfo = cIInfo;
Expand All @@ -51,6 +53,7 @@ public TestProcessor(CloudRunMetadata cloudRunMetadata, CIInfo cIInfo, ILogger?
_cloudRunErrorParser = cloudRunErrorParser ?? new CloudRunErrorParser(_logger);
_serviceClient = serviceClient ?? new ServiceClient(_cloudRunMetadata, _cloudRunErrorParser);
_consoleWriter = consoleWriter ?? new ConsoleWriter();
_blobService = blobService ?? new BlobService(_logger);
}

public void TestRunStartHandler(object? sender, TestRunStartEventArgs e)
Expand Down Expand Up @@ -171,7 +174,7 @@ public void TestRunCompleteHandler(object? sender, TestRunCompleteEventArgs e)
// Upload rawResult to blob storage using sasUri
var rawTestResultJson = JsonSerializer.Serialize(rawResult);
var filePath = $"{testResult.TestExecutionId}/rawTestResult.json";
UploadBuffer(sasUri!.Uri!, rawTestResultJson, filePath);
_blobService.UploadBufferAsync(sasUri!.Uri!, rawTestResultJson, filePath);
}
else
{
Expand Down Expand Up @@ -215,9 +218,9 @@ private void UploadAttachment(TestResultEventArgs e, string testExecutionId)
{
// get file size
var fileSize = new FileInfo(filePath).Length;
var cloudFileName = ReporterUtils.GetCloudFileName(filePath, testExecutionId);
var cloudFileName = _blobService.GetCloudFileName(filePath, testExecutionId);
if (cloudFileName != null) {
UploadBlobFile(_testResultsSasUri!.Uri!, cloudFileName, filePath);
_blobService.UploadBlobFile(_testResultsSasUri!.Uri!, cloudFileName, filePath);
TotalArtifactCount++;
TotalArtifactSizeInBytes = TotalArtifactSizeInBytes + (int)fileSize;
}
Expand All @@ -237,7 +240,7 @@ private void UploadAttachment(TestResultEventArgs e, string testExecutionId)
}
}

private TestResultsUri? CheckAndRenewSasUri()
internal TestResultsUri? CheckAndRenewSasUri()
{
var reporterUtils = new ReporterUtils();
if (_testResultsSasUri == null || !reporterUtils.IsTimeGreaterThanCurrentPlus10Minutes(_testResultsSasUri.Uri))
Expand Down Expand Up @@ -270,31 +273,6 @@ private void EndTestRun(TestRunCompleteEventArgs e)
}
_cloudRunErrorParser.DisplayMessages();
}
private static string GetCloudFilePath(string uri, string fileRelativePath)
{
string[] parts = uri.Split(new string[] { ReporterConstants.s_sASUriSeparator }, StringSplitOptions.None);
string containerUri = parts[0];
string sasToken = parts.Length > 1 ? parts[1] : string.Empty;

return $"{containerUri}/{fileRelativePath}?{sasToken}";
}
private void UploadBuffer(string uri, string buffer, string fileRelativePath)
{
string cloudFilePath = GetCloudFilePath(uri, fileRelativePath);
BlobClient blobClient = new(new Uri(cloudFilePath));
byte[] bufferBytes = Encoding.UTF8.GetBytes(buffer);
blobClient.Upload(new BinaryData(bufferBytes), overwrite: true);
_logger.Info($"Uploaded buffer to {fileRelativePath}");
}

private void UploadBlobFile(string uri, string fileRelativePath, string filePath)
{
string cloudFilePath = GetCloudFilePath(uri, fileRelativePath);
BlobClient blobClient = new(new Uri(cloudFilePath));
// Upload filePath to Blob
blobClient.Upload(filePath, overwrite: true);
_logger.Info($"Uploaded file {filePath} to {fileRelativePath}");
}

private TestRunShardDto GetTestRunEndShard(TestRunCompleteEventArgs e)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,6 @@ internal static string GetCurrentOS()
else
return OSConstants.s_wINDOWS;
}
internal static string? GetCloudFileName(string filePath, string testExecutionId)
{
var fileName = Path.GetFileName(filePath);
if (fileName == null)
{
return null;
}
return $"{testExecutionId}/{fileName}"; // TODO check if we need to add {Guid.NewGuid()} for file with same name
}

internal TokenDetails ParseWorkspaceIdFromAccessToken(JsonWebTokenHandler? jsonWebTokenHandler, string? accessToken)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Text;
using System.Threading.Tasks;
using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Implementation;
using Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Interface;
using Moq;
using NUnit.Framework;

namespace Azure.Developer.MicrosoftPlaywrightTesting.TestLogger.Tests.Implementation
{
[TestFixture]
[Parallelizable(ParallelScope.Self)]
public class BlobServiceTests
{
private Mock<ILogger>? _loggerMock;
private BlobService? _blobService;

[SetUp]
public void Setup()
{
_loggerMock = new Mock<ILogger>();
_blobService = new BlobService(_loggerMock.Object);
}
[Test]
public async Task UploadBufferAsync_WithException_LogsError()
{
string uri = "invalid_uri";
string buffer = "Test buffer";
string fileRelativePath = "test/path";

await _blobService!.UploadBufferAsync(uri, buffer, fileRelativePath);

_loggerMock!.Verify(logger => logger.Error(It.IsAny<string>()), Times.Once);
}

[Test]
public void GetCloudFilePath_WithValidParameters_ReturnsCorrectPath()
{
string uri = "https://example.com/container";
string fileRelativePath = "test/path";
string expectedPath = "https://example.com/container/test/path?";

string? result = _blobService?.GetCloudFilePath(uri, fileRelativePath);

Assert.AreEqual(expectedPath, result);
}

[Test]
public void GetCloudFilePath_WithSasUri_ReturnsCorrectPath()
{
string uri = "https://example.com/container?sasToken";
string fileRelativePath = "test/path";
string expectedPath = "https://example.com/container/test/path?sasToken";

string? result = _blobService?.GetCloudFilePath(uri, fileRelativePath);

Assert.AreEqual(expectedPath, result);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -580,5 +580,38 @@ public void TestRunCompleteHandler_EnableResultPublishSetToFalse_DisplaysMessage
serviceClientMock.Verify(c => c.PostTestRunShardInfo(It.IsAny<TestRunShardDto>()), Times.Never);
cloudRunErrorParserMock.Verify(c => c.DisplayMessages(), Times.Exactly(1));
}
[Test]
public void CheckAndRenewSasUri_WhenUriExpired_FetchesNewSasUri()
{
var loggerMock = new Mock<ILogger>();
var dataProcessorMock = new Mock<IDataProcessor>();
var consoleWriterMock = new Mock<IConsoleWriter>();
var cloudRunErrorParserMock = new Mock<ICloudRunErrorParser>();
var serviceClientMock = new Mock<IServiceClient>();
var testProcessor = new TestProcessor(_cloudRunMetadata, _cIInfo, loggerMock.Object, dataProcessorMock.Object, cloudRunErrorParserMock.Object, serviceClientMock.Object, consoleWriterMock.Object);
var expiredTestResultsSasUri = new TestResultsUri { Uri = "http://example.com", ExpiresAt = DateTime.UtcNow.AddMinutes(-5).ToString(), AccessLevel = AccessLevel.Read };
var newTestResultsSasUri = new TestResultsUri { Uri = "http://newexample.com", ExpiresAt = DateTime.UtcNow.AddHours(1).ToString(), AccessLevel = AccessLevel.Read };
testProcessor._testResultsSasUri = expiredTestResultsSasUri;
serviceClientMock.Setup(sc => sc.GetTestRunResultsUri()).Returns(newTestResultsSasUri);
TestResultsUri? result = testProcessor.CheckAndRenewSasUri();
Assert.AreEqual(newTestResultsSasUri, result);
loggerMock.Verify(l => l.Info(It.IsAny<string>()), Times.AtLeastOnce);
}
[Test]
public void CheckAndRenewSasUri_WhenUriNotExpired_DoesNotFetchNewSasUri()
{
var loggerMock = new Mock<ILogger>();
var dataProcessorMock = new Mock<IDataProcessor>();
var consoleWriterMock = new Mock<IConsoleWriter>();
var cloudRunErrorParserMock = new Mock<ICloudRunErrorParser>();
var serviceClientMock = new Mock<IServiceClient>();
var testProcessor = new TestProcessor(_cloudRunMetadata, _cIInfo, loggerMock.Object, dataProcessorMock.Object, cloudRunErrorParserMock.Object, serviceClientMock.Object, consoleWriterMock.Object);
var validTestResultsSasUri = new TestResultsUri { Uri = "http://example.com?se=" + DateTime.UtcNow.AddMinutes(15).ToString("o"), ExpiresAt = DateTime.UtcNow.AddMinutes(15).ToString(), AccessLevel = AccessLevel.Read };
testProcessor._testResultsSasUri = validTestResultsSasUri;
TestResultsUri? result = testProcessor.CheckAndRenewSasUri();
Assert.AreEqual(validTestResultsSasUri, result);
serviceClientMock.Verify(sc => sc.GetTestRunResultsUri(), Times.Never);
loggerMock.Verify(l => l.Info(It.IsAny<string>()), Times.Never);
}
}
}

0 comments on commit 52190ed

Please sign in to comment.