210 lines
7.1 KiB
C#
Executable File
210 lines
7.1 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 DevOpsScanPluginTests
|
|
{
|
|
private DevOpsScanPlugin _plugin;
|
|
private Mock<ILogger<DevOpsScanPlugin>> _mockLogger;
|
|
private string _testDataPath;
|
|
|
|
[TestInitialize]
|
|
public void Setup()
|
|
{
|
|
_mockLogger = new Mock<ILogger<DevOpsScanPlugin>>();
|
|
_plugin = new DevOpsScanPlugin(_mockLogger.Object);
|
|
|
|
// Find the project directory by traversing up from the assembly location
|
|
var assemblyLocation = Path.GetDirectoryName(typeof(DevOpsScanPluginTests).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", "SamplePipelines");
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task ExecuteAsync_GitHubActions_ReturnsValidAnalysis()
|
|
{
|
|
// Arrange
|
|
var githubFile = Path.Combine(_testDataPath, "github-actions-sample.yml");
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["pipelinePath"] = githubFile,
|
|
["pipelineType"] = "github",
|
|
["checkSecurity"] = true,
|
|
["optimizeBuild"] = true,
|
|
["checkBestPractices"] = true,
|
|
["generateRecommendations"] = true
|
|
};
|
|
|
|
// Act
|
|
var result = await _plugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
Assert.IsNotNull(result.Data);
|
|
|
|
var data = result.Data as dynamic;
|
|
Assert.IsNotNull(data);
|
|
Assert.AreEqual("DevOps pipeline scan completed", data.GetType().GetProperty("Message")?.GetValue(data));
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task ExecuteAsync_NonExistentFile_ReturnsError()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["pipelinePath"] = "/nonexistent/path/pipeline.yml"
|
|
};
|
|
|
|
// 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_DetectsIssues()
|
|
{
|
|
// Arrange
|
|
var tempFile = Path.GetTempFileName();
|
|
var insecureContent = @"
|
|
name: Insecure Pipeline
|
|
on: [push]
|
|
jobs:
|
|
build:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@main
|
|
- name: Deploy
|
|
env:
|
|
API_KEY: ghp_1234567890abcdefghijklmnopqrstuvwxyz12
|
|
run: echo 'Deploying'
|
|
";
|
|
await File.WriteAllTextAsync(tempFile, insecureContent);
|
|
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["pipelinePath"] = tempFile,
|
|
["pipelineType"] = "github",
|
|
["checkSecurity"] = true
|
|
};
|
|
|
|
try
|
|
{
|
|
// 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);
|
|
}
|
|
finally
|
|
{
|
|
if (File.Exists(tempFile))
|
|
File.Delete(tempFile);
|
|
}
|
|
}
|
|
|
|
|
|
[TestMethod]
|
|
public void SupportedParameters_ReturnsExpectedParameters()
|
|
{
|
|
// Act
|
|
var parameters = _plugin.SupportedParameters;
|
|
|
|
// Assert
|
|
Assert.IsNotNull(parameters);
|
|
Assert.IsTrue(parameters.ContainsKey("pipelinePath"));
|
|
Assert.IsTrue(parameters.ContainsKey("pipelineType"));
|
|
Assert.IsTrue(parameters.ContainsKey("checkSecurity"));
|
|
Assert.IsTrue(parameters.ContainsKey("optimizeBuild"));
|
|
Assert.IsTrue(parameters.ContainsKey("checkBestPractices"));
|
|
Assert.IsTrue(parameters.ContainsKey("generateRecommendations"));
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task ExecuteAsync_AzureDevOps_ParsesBasicStructure()
|
|
{
|
|
// Arrange
|
|
var azureFile = Path.Combine(_testDataPath, "azure-pipelines-sample.yml");
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["pipelinePath"] = azureFile,
|
|
["pipelineType"] = "azure"
|
|
};
|
|
|
|
// Act
|
|
var result = await _plugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
var data = result.Data as dynamic;
|
|
Assert.IsNotNull(data);
|
|
Assert.AreEqual("azure", data.GetType().GetProperty("PipelineType")?.GetValue(data));
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task ExecuteAsync_GitLabCI_ParsesBasicStructure()
|
|
{
|
|
// Arrange
|
|
var gitlabFile = Path.Combine(_testDataPath, "gitlab-ci-sample.yml");
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["pipelinePath"] = gitlabFile,
|
|
["pipelineType"] = "gitlab"
|
|
};
|
|
|
|
// Act
|
|
var result = await _plugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
var data = result.Data as dynamic;
|
|
Assert.IsNotNull(data);
|
|
Assert.AreEqual("gitlab", data.GetType().GetProperty("PipelineType")?.GetValue(data));
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task ExecuteAsync_AutoDetection_DetectsGitHubActions()
|
|
{
|
|
// Arrange
|
|
var githubFile = Path.Combine(_testDataPath, "github-actions-sample.yml");
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["pipelinePath"] = githubFile,
|
|
["pipelineType"] = "auto"
|
|
};
|
|
|
|
// Act
|
|
var result = await _plugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
// Note: Auto-detection would need the file to be in .github/workflows/ directory
|
|
// This test validates the auto parameter is handled correctly
|
|
}
|
|
}
|
|
} |