namespace ZB.MOM.WW.Secrets.Replicator.SqlServer.Tests; /// /// The schema-name allow-list is the injection boundary for the one value that cannot be /// parameterized (a T-SQL object name), so it gets adversarial coverage rather than a happy path. /// public sealed class SqlServerSecretsOptionsTests { [Theory] [InlineData("zbsecrets")] [InlineData("ZbSecrets")] [InlineData("_private")] [InlineData("schema_1")] public void SchemaName_accepts_plain_identifiers(string value) { var options = new SqlServerSecretsOptions { SchemaName = value }; Assert.Equal(value, options.SchemaName); } [Theory] // The bracket-escape trick that would otherwise break out of the [quoting] at the use site. [InlineData("evil]]; DROP TABLE secret; --")] [InlineData("dbo.secret")] [InlineData("with space")] [InlineData("quote'name")] [InlineData("semi;colon")] [InlineData("1leading_digit")] [InlineData("")] [InlineData(" ")] public void SchemaName_rejects_anything_that_is_not_a_plain_identifier(string value) { Assert.Throws(() => new SqlServerSecretsOptions { SchemaName = value }); } [Fact] public void SchemaName_rejects_an_over_long_identifier() { Assert.Throws(() => new SqlServerSecretsOptions { SchemaName = new string('a', 129) }); } [Fact] public void Validate_rejects_a_missing_connection_string() { InvalidOperationException ex = Assert.Throws(() => new SqlServerSecretsOptions().Validate()); Assert.Contains("ConnectionString", ex.Message, StringComparison.Ordinal); } [Fact] public void Validate_rejects_a_non_positive_sync_interval() { var options = new SqlServerSecretsOptions { ConnectionString = "Server=x;", SyncInterval = TimeSpan.Zero, }; Assert.Throws(options.Validate); } [Fact] public void Validate_rejects_a_non_positive_command_timeout() { var options = new SqlServerSecretsOptions { ConnectionString = "Server=x;", CommandTimeout = TimeSpan.FromSeconds(-1), }; Assert.Throws(options.Validate); } [Fact] public void Validate_accepts_a_fully_configured_instance() { var options = new SqlServerSecretsOptions { ConnectionString = "Server=x;Database=y;" }; options.Validate(); } [Fact] public void CreateSchemaDdl_quotes_the_schema_name_everywhere_it_appears() { string ddl = SqlServerSecretsSchema.CreateSchemaDdl("zbsecrets"); Assert.Contains("[zbsecrets].[secret]", ddl, StringComparison.Ordinal); Assert.Contains("[zbsecrets].[schema_version]", ddl, StringComparison.Ordinal); // Every DDL statement is guarded, so re-running the migration on a provisioned database is // a no-op rather than an error. Assert.Contains("IF NOT EXISTS", ddl, StringComparison.Ordinal); Assert.Contains("IS NULL", ddl, StringComparison.Ordinal); } }