216 lines
7.6 KiB
C#
Executable File
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);
|
|
}
|
|
}
|
|
}
|
|
} |