MarketAlly.AIPlugin.Extensions/MarketAlly.AIPlugin.DevOps/Tests/DockerfileAnalyzerPluginTes...

216 lines
7.6 KiB
C#
Executable File

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Extensions.Logging;
using MarketAlly.AIPlugin.DevOps.Plugins;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Moq;
namespace MarketAlly.AIPlugin.DevOps.Tests
{
[TestClass]
public class DockerfileAnalyzerPluginTests
{
private DockerfileAnalyzerPlugin _plugin;
private Mock<ILogger<DockerfileAnalyzerPlugin>> _mockLogger;
private string _testDataPath;
[TestInitialize]
public void Setup()
{
_mockLogger = new Mock<ILogger<DockerfileAnalyzerPlugin>>();
_plugin = new DockerfileAnalyzerPlugin(_mockLogger.Object);
// Find the project directory by traversing up from the assembly location
var assemblyLocation = Path.GetDirectoryName(typeof(DockerfileAnalyzerPluginTests).Assembly.Location);
var projectDir = assemblyLocation;
while (projectDir != null && !Directory.Exists(Path.Combine(projectDir, "Tests", "TestData")))
{
projectDir = Directory.GetParent(projectDir)?.FullName;
}
_testDataPath = Path.Combine(projectDir ?? assemblyLocation, "Tests", "TestData", "SampleDockerfiles");
}
[TestMethod]
public async Task ExecuteAsync_ProblematicDockerfile_DetectsIssues()
{
// Arrange
var dockerfilePath = Path.Combine(_testDataPath, "Dockerfile.issues");
var parameters = new Dictionary<string, object>
{
["dockerfilePath"] = dockerfilePath,
["checkSecurity"] = true,
["optimizeSize"] = true,
["checkBestPractices"] = true
};
// Act
var result = await _plugin.ExecuteAsync(parameters);
// Assert
Assert.IsTrue(result.Success);
var data = result.Data as dynamic;
Assert.IsNotNull(data);
// Should detect security issues
var securityIssues = data.GetType().GetProperty("SecurityIssues")?.GetValue(data) as System.Collections.IList;
Assert.IsNotNull(securityIssues);
Assert.IsTrue(securityIssues.Count > 0);
// Should detect size optimization opportunities
var sizeOptimizations = data.GetType().GetProperty("SizeOptimizations")?.GetValue(data) as System.Collections.IList;
Assert.IsNotNull(sizeOptimizations);
Assert.IsTrue(sizeOptimizations.Count > 0);
// Should detect best practice violations
var bestPracticeViolations = data.GetType().GetProperty("BestPracticeViolations")?.GetValue(data) as System.Collections.IList;
Assert.IsNotNull(bestPracticeViolations);
Assert.IsTrue(bestPracticeViolations.Count > 0);
}
[TestMethod]
public async Task ExecuteAsync_NonExistentDockerfile_ReturnsError()
{
// Arrange
var parameters = new Dictionary<string, object>
{
["dockerfilePath"] = "/nonexistent/Dockerfile"
};
// Act
var result = await _plugin.ExecuteAsync(parameters);
// Assert
Assert.IsFalse(result.Success);
Assert.IsNotNull(result.Error);
Assert.IsTrue(result.Error is FileNotFoundException);
}
[TestMethod]
public async Task ExecuteAsync_SecurityCheck_DetectsHardcodedSecrets()
{
// Arrange
var tempFile = Path.GetTempFileName();
var insecureDockerfile = @"
FROM ubuntu:latest
ENV API_KEY=supersecretkey123
ENV DATABASE_PASSWORD=mypassword456
RUN echo $API_KEY > /tmp/key
";
await File.WriteAllTextAsync(tempFile, insecureDockerfile);
var parameters = new Dictionary<string, object>
{
["dockerfilePath"] = tempFile,
["checkSecurity"] = true
};
try
{
// Act
var result = await _plugin.ExecuteAsync(parameters);
// Assert
Assert.IsTrue(result.Success);
var data = result.Data as dynamic;
Assert.IsNotNull(data);
var securityIssues = data.GetType().GetProperty("SecurityIssues")?.GetValue(data) as System.Collections.IList;
Assert.IsNotNull(securityIssues);
Assert.IsTrue(securityIssues.Count > 0);
}
finally
{
if (File.Exists(tempFile))
File.Delete(tempFile);
}
}
[TestMethod]
public async Task ExecuteAsync_MultiStageAnalysis_DetectsMultiStage()
{
// Arrange
var dockerfilePath = Path.Combine(_testDataPath, "Dockerfile.good");
var parameters = new Dictionary<string, object>
{
["dockerfilePath"] = dockerfilePath,
["checkMultiStage"] = true
};
// Act
var result = await _plugin.ExecuteAsync(parameters);
// Assert
Assert.IsTrue(result.Success);
var data = result.Data as dynamic;
Assert.IsNotNull(data);
var multiStageAnalysis = data.GetType().GetProperty("MultiStageAnalysis")?.GetValue(data);
Assert.IsNotNull(multiStageAnalysis);
var isMultiStage = (bool)multiStageAnalysis.GetType().GetProperty("IsMultiStage")?.GetValue(multiStageAnalysis);
Assert.IsTrue(isMultiStage); // Good dockerfile uses multi-stage build
}
[TestMethod]
public void SupportedParameters_ReturnsExpectedParameters()
{
// Act
var parameters = _plugin.SupportedParameters;
// Assert
Assert.IsNotNull(parameters);
Assert.IsTrue(parameters.ContainsKey("dockerfilePath"));
Assert.IsTrue(parameters.ContainsKey("checkSecurity"));
Assert.IsTrue(parameters.ContainsKey("optimizeSize"));
Assert.IsTrue(parameters.ContainsKey("checkBestPractices"));
Assert.IsTrue(parameters.ContainsKey("checkMultiStage"));
Assert.IsTrue(parameters.ContainsKey("generateOptimized"));
}
[TestMethod]
public async Task ExecuteAsync_SizeOptimization_DetectsConsecutiveRuns()
{
// Arrange
var tempFile = Path.GetTempFileName();
var unoptimizedDockerfile = @"
FROM ubuntu:latest
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y wget
RUN apt-get install -y git
";
await File.WriteAllTextAsync(tempFile, unoptimizedDockerfile);
var parameters = new Dictionary<string, object>
{
["dockerfilePath"] = tempFile,
["optimizeSize"] = true
};
try
{
// Act
var result = await _plugin.ExecuteAsync(parameters);
// Assert
Assert.IsTrue(result.Success);
var data = result.Data as dynamic;
Assert.IsNotNull(data);
var sizeOptimizations = data.GetType().GetProperty("SizeOptimizations")?.GetValue(data) as System.Collections.IList;
Assert.IsNotNull(sizeOptimizations);
Assert.IsTrue(sizeOptimizations.Count > 0);
}
finally
{
if (File.Exists(tempFile))
File.Delete(tempFile);
}
}
}
}