Files
git.stella-ops.org/tests/integration/StellaOps.Integration.Platform/PostgresOnlyStartupTests.cs
StellaOps Bot 5146204f1b feat: add security sink detection patterns for JavaScript/TypeScript
- Introduced `sink-detect.js` with various security sink detection patterns categorized by type (e.g., command injection, SQL injection, file operations).
- Implemented functions to build a lookup map for fast sink detection and to match sink calls against known patterns.
- Added `package-lock.json` for dependency management.
2025-12-22 23:21:21 +02:00

249 lines
9.2 KiB
C#

// -----------------------------------------------------------------------------
// PostgresOnlyStartupTests.cs
// Sprint: SPRINT_5100_0001_0001_mongodb_cli_cleanup_consolidation
// Task: T1.13 - PostgreSQL-only Platform Startup Test
// Description: Validates platform can start with PostgreSQL-only infrastructure.
// -----------------------------------------------------------------------------
using System.Reflection;
using StellaOps.Infrastructure.Postgres.Testing;
using Testcontainers.PostgreSql;
namespace StellaOps.Integration.Platform;
/// <summary>
/// Integration tests validating PostgreSQL-only platform startup.
/// </summary>
/// <remarks>
/// T1.13-AC1: Platform starts successfully with PostgreSQL only
/// T1.13-AC2: All services connect to PostgreSQL correctly
/// T1.13-AC3: Schema migrations run successfully
/// T1.13-AC4: No MongoDB connection attempts in logs
/// </remarks>
[Trait("Category", "Integration")]
[Trait("Category", "Platform")]
[Trait("Category", "PostgresOnly")]
public class PostgresOnlyStartupTests : IAsyncLifetime
{
private PostgreSqlContainer? _container;
private string? _connectionString;
public async Task InitializeAsync()
{
_container = new PostgreSqlBuilder()
.WithImage("postgres:16-alpine")
.Build();
await _container.StartAsync();
_connectionString = _container.GetConnectionString();
}
public async Task DisposeAsync()
{
if (_container != null)
{
await _container.DisposeAsync();
}
}
#region T1.13-AC1: Platform starts successfully with PostgreSQL only
[Fact(DisplayName = "T1.13-AC1.1: PostgreSQL container starts and accepts connections")]
public async Task PostgresContainer_StartsAndAcceptsConnections()
{
// Arrange & Act - already done in InitializeAsync
// Assert
_connectionString.Should().NotBeNullOrEmpty();
_container!.State.Should().Be(DotNet.Testcontainers.Containers.TestcontainersStates.Running);
// Verify connection works
using var connection = new Npgsql.NpgsqlConnection(_connectionString);
await connection.OpenAsync();
connection.State.Should().Be(System.Data.ConnectionState.Open);
}
[Fact(DisplayName = "T1.13-AC1.2: PostgreSQL connection string contains no MongoDB references")]
public void ConnectionString_ContainsNoMongoDbReferences()
{
// Assert
_connectionString.Should().NotContainAny("mongo", "mongodb", "27017");
}
#endregion
#region T1.13-AC2: Services connect to PostgreSQL correctly
[Fact(DisplayName = "T1.13-AC2.1: Can create and verify database schema")]
public async Task Database_CanCreateAndVerifySchema()
{
// Arrange
using var connection = new Npgsql.NpgsqlConnection(_connectionString);
await connection.OpenAsync();
// Act - Create a test schema
using var createCmd = connection.CreateCommand();
createCmd.CommandText = "CREATE SCHEMA IF NOT EXISTS test_platform";
await createCmd.ExecuteNonQueryAsync();
// Assert - Verify schema exists
using var verifyCmd = connection.CreateCommand();
verifyCmd.CommandText = @"
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name = 'test_platform'";
var result = await verifyCmd.ExecuteScalarAsync();
result.Should().Be("test_platform");
}
[Fact(DisplayName = "T1.13-AC2.2: Can perform basic CRUD operations")]
public async Task Database_CanPerformCrudOperations()
{
// Arrange
using var connection = new Npgsql.NpgsqlConnection(_connectionString);
await connection.OpenAsync();
// Create test table
using var createCmd = connection.CreateCommand();
createCmd.CommandText = @"
CREATE TABLE IF NOT EXISTS test_crud (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
)";
await createCmd.ExecuteNonQueryAsync();
// Act - Insert
using var insertCmd = connection.CreateCommand();
insertCmd.CommandText = "INSERT INTO test_crud (name) VALUES ('test-record') RETURNING id";
var insertedId = await insertCmd.ExecuteScalarAsync();
insertedId.Should().NotBeNull();
// Act - Select
using var selectCmd = connection.CreateCommand();
selectCmd.CommandText = "SELECT name FROM test_crud WHERE id = @id";
selectCmd.Parameters.AddWithValue("id", insertedId!);
var name = await selectCmd.ExecuteScalarAsync();
name.Should().Be("test-record");
// Act - Update
using var updateCmd = connection.CreateCommand();
updateCmd.CommandText = "UPDATE test_crud SET name = 'updated-record' WHERE id = @id";
updateCmd.Parameters.AddWithValue("id", insertedId!);
var rowsAffected = await updateCmd.ExecuteNonQueryAsync();
rowsAffected.Should().Be(1);
// Act - Delete
using var deleteCmd = connection.CreateCommand();
deleteCmd.CommandText = "DELETE FROM test_crud WHERE id = @id";
deleteCmd.Parameters.AddWithValue("id", insertedId!);
rowsAffected = await deleteCmd.ExecuteNonQueryAsync();
rowsAffected.Should().Be(1);
}
#endregion
#region T1.13-AC3: Schema migrations run successfully
[Fact(DisplayName = "T1.13-AC3.1: Can run DDL migrations")]
public async Task Database_CanRunDdlMigrations()
{
// Arrange
using var connection = new Npgsql.NpgsqlConnection(_connectionString);
await connection.OpenAsync();
// Act - Run a migration-like DDL script
var migrationScript = @"
-- V1: Create migrations tracking table
CREATE TABLE IF NOT EXISTS schema_migrations (
version VARCHAR(50) PRIMARY KEY,
applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
checksum VARCHAR(64) NOT NULL
);
-- V2: Create sample domain table
CREATE TABLE IF NOT EXISTS scan_results (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
image_ref TEXT NOT NULL,
findings_count INT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Record migration
INSERT INTO schema_migrations (version, checksum)
VALUES ('V2_create_scan_results', 'abc123')
ON CONFLICT (version) DO NOTHING;
";
using var migrateCmd = connection.CreateCommand();
migrateCmd.CommandText = migrationScript;
await migrateCmd.ExecuteNonQueryAsync();
// Assert - Verify migration recorded
using var verifyCmd = connection.CreateCommand();
verifyCmd.CommandText = "SELECT COUNT(*) FROM schema_migrations WHERE version = 'V2_create_scan_results'";
var count = await verifyCmd.ExecuteScalarAsync();
Convert.ToInt32(count).Should().Be(1);
}
[Fact(DisplayName = "T1.13-AC3.2: PostgreSQL extensions can be created")]
public async Task Database_CanCreateExtensions()
{
// Arrange
using var connection = new Npgsql.NpgsqlConnection(_connectionString);
await connection.OpenAsync();
// Act - Create common extensions used by StellaOps
using var extCmd = connection.CreateCommand();
extCmd.CommandText = "CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\"";
await extCmd.ExecuteNonQueryAsync();
// Assert - Verify extension exists
using var verifyCmd = connection.CreateCommand();
verifyCmd.CommandText = "SELECT COUNT(*) FROM pg_extension WHERE extname = 'uuid-ossp'";
var count = await verifyCmd.ExecuteScalarAsync();
Convert.ToInt32(count).Should().Be(1);
}
#endregion
#region T1.13-AC4: No MongoDB connection attempts
[Fact(DisplayName = "T1.13-AC4.1: Environment variables contain no MongoDB references")]
public void EnvironmentVariables_ContainNoMongoDbReferences()
{
// Arrange - Get all environment variables
var envVars = Environment.GetEnvironmentVariables();
// Act & Assert
foreach (string key in envVars.Keys)
{
var value = envVars[key]?.ToString() ?? "";
// Skip if this is our test connection string
if (key.Contains("POSTGRES", StringComparison.OrdinalIgnoreCase))
continue;
key.Should().NotContainEquivalentOf("mongo",
$"Environment variable key '{key}' should not reference MongoDB");
}
}
[Fact(DisplayName = "T1.13-AC4.2: PostgreSQL-only configuration is valid")]
public void Configuration_IsPostgresOnly()
{
// This test documents the expected configuration pattern
var expectedConfig = new Dictionary<string, string>
{
["STELLAOPS_STORAGE_DRIVER"] = "postgres",
["STELLAOPS_CACHE_DRIVER"] = "valkey", // or "redis" for compatibility
};
// Assert - Document the expected pattern
expectedConfig["STELLAOPS_STORAGE_DRIVER"].Should().NotBe("mongodb");
expectedConfig["STELLAOPS_STORAGE_DRIVER"].Should().Be("postgres");
}
#endregion
}