public async Task GetResourceAsync_ReturnsNullIfSdkThrowsNotFound()
        {
            var dynamoDbFake = new Mock <IAmazonDynamoDB>();

            dynamoDbFake
            .Setup(s => s.ListTablesAsync(
                       It.Is <string>(r => r == null), It.IsAny <CancellationToken>()
                       ))
            .ReturnsAsync(new ListTablesResponse()
            {
                TableNames = new List <string>()
                {
                    "banana"
                }
            });

            dynamoDbFake
            .Setup(s => s.DescribeTableAsync("banana", It.IsAny <CancellationToken>()))
            .Throws(new ResourceNotFoundException("Table not found"))
            //so we know we actually threw this error
            .Verifiable();

            var sut = new TableDescriptionSource(dynamoDbFake.Object);

            var result = await sut.GetResourceAsync("banana");

            dynamoDbFake.Verify();

            Assert.Null(result);
        }
        public void Setup()
        {
            var firstTableName = "Table-1";

            _firstPage = new ListTablesResponse
            {
                LastEvaluatedTableName = firstTableName,
                TableNames             = new List <string>
                {
                    firstTableName
                }
            };
            var secondTableName = "Table-2";

            _secondPage = new ListTablesResponse
            {
                LastEvaluatedTableName = secondTableName,
                TableNames             = new List <string>
                {
                    secondTableName
                }
            };
            _thirdPage = new ListTablesResponse
            {
                TableNames = new List <string>
                {
                    "Table-3"
                }
            };

            var describeSecondTableResponse = new DescribeTableResponse
            {
                Table = new TableDescription
                {
                    TableName = secondTableName
                }
            };

            var dynamoDbMock = new Mock <IAmazonDynamoDB>();

            dynamoDbMock.Setup(s => s.ListTablesAsync(
                                   It.Is <string>(r => r == null), It.IsAny <CancellationToken>()
                                   )).ReturnsAsync(_firstPage);

            dynamoDbMock.Setup(s => s.ListTablesAsync(
                                   It.Is <string>(r => r == firstTableName),
                                   It.IsAny <CancellationToken>()
                                   )).ReturnsAsync(_secondPage);

            dynamoDbMock.Setup(s => s.ListTablesAsync(
                                   It.Is <string>(r => r == secondTableName),
                                   It.IsAny <CancellationToken>()
                                   )).ReturnsAsync(_thirdPage);

            dynamoDbMock.Setup(s => s.DescribeTableAsync(It.Is <string>(r => r == secondTableName),
                                                         It.IsAny <CancellationToken>()))
            .ReturnsAsync(describeSecondTableResponse);

            _tableDescriptionSource = new TableDescriptionSource(dynamoDbMock.Object);
        }
        public async Task IgnoresNamedEntitiesThatDoNotExist()
        {
            // arrange

            var stack = new Mock <ICloudformationStackDeployer>();

            var dynamoClient = CreateDynamoClientForTables(new[]
            {
                new TableDescription()
                {
                    TableName             = "first-dynamo-table",
                    ProvisionedThroughput = new ProvisionedThroughputDescription()
                    {
                        ReadCapacityUnits  = 10,
                        WriteCapacityUnits = 10
                    }
                }
            });

            var source = new TableDescriptionSource(dynamoClient);

            var creator = new CloudFormationAlarmCreator(stack.Object, new ConsoleAlarmLogger(true));

            var config = ConfigHelper.CreateBasicConfiguration("test", "group-suffix", "DynamoDb", new List <ResourceThresholds>()
            {
                new ResourceThresholds()
                {
                    Name = "non-existant-table"
                }
            });

            var sut = IoCHelper.CreateSystemUnderTest(
                source,
                new DynamoDbDataProvider(),
                new DynamoDbDataProvider(),
                WatchmanServiceConfigurationMapper.MapDynamoDb,
                creator,
                ConfigHelper.ConfigLoaderFor(config)
                );



            // act

            await sut.LoadAndGenerateAlarms(RunMode.GenerateAlarms);

            // assert

            stack
            .Verify(x => x.DeployStack(
                        It.IsAny <string>(),
                        It.IsAny <string>(),
                        It.IsAny <bool>()
                        ), Times.Never);
        }
        public async Task AlarmCreatedWithCorrectProperties()
        {
            // arrange

            var stack = new FakeStackDeployer();

            var dynamoClient = CreateDynamoClientForTables(new[]
            {
                new TableDescription()
                {
                    TableName             = "first-dynamo-table",
                    ProvisionedThroughput = new ProvisionedThroughputDescription()
                    {
                        ReadCapacityUnits  = 100,
                        WriteCapacityUnits = 200
                    }
                }
            });

            var source  = new TableDescriptionSource(dynamoClient);
            var creator = new CloudFormationAlarmCreator(stack, new ConsoleAlarmLogger(true));

            var config = ConfigHelper.CreateBasicConfiguration("test", "group-suffix", "DynamoDb", new List <ResourceThresholds>()
            {
                new ResourceThresholds()
                {
                    Name = "first-dynamo-table"
                }
            });

            var sut = IoCHelper.CreateSystemUnderTest(
                source,
                new DynamoDbDataProvider(),
                new DynamoDbDataProvider(),
                WatchmanServiceConfigurationMapper.MapDynamoDb,
                creator, ConfigHelper.ConfigLoaderFor(config)
                );

            // act

            await sut.LoadAndGenerateAlarms(RunMode.GenerateAlarms);

            // assert

            const decimal defaultCapacityThresholdFraction = 0.8m;
            const int     defaultThrottleThreshold         = 2;

            var alarmsByTable = stack
                                .Stack("Watchman-test")
                                .AlarmsByDimension("TableName");

            Assert.That(alarmsByTable.ContainsKey("first-dynamo-table"), Is.True);
            var alarms = alarmsByTable["first-dynamo-table"];

            Assert.That(alarms.Exists(
                            alarm =>
                            alarm.Properties["MetricName"].Value <string>() == "ConsumedReadCapacityUnits" &&
                            alarm.Properties["AlarmName"].Value <string>().Contains("ConsumedReadCapacityUnitsHigh") &&
                            alarm.Properties["Threshold"].Value <int>() == 100 * defaultCapacityThresholdFraction &&
                            alarm.Properties["Period"].Value <int>() == 60 &&
                            alarm.Properties["ComparisonOperator"].Value <string>() == "GreaterThanOrEqualToThreshold" &&
                            alarm.Properties["Statistic"].Value <string>() == "Sum" &&
                            alarm.Properties["Namespace"].Value <string>() == AwsNamespace.DynamoDb
                            )
                        );

            Assert.That(alarms.Exists(
                            alarm =>
                            alarm.Properties["MetricName"].Value <string>() == "ConsumedWriteCapacityUnits" &&
                            alarm.Properties["AlarmName"].Value <string>().Contains("ConsumedWriteCapacityUnitsHigh") &&
                            alarm.Properties["Threshold"].Value <int>() == 200 * defaultCapacityThresholdFraction &&
                            alarm.Properties["Period"].Value <int>() == 60 &&
                            alarm.Properties["ComparisonOperator"].Value <string>() == "GreaterThanOrEqualToThreshold" &&
                            alarm.Properties["Statistic"].Value <string>() == "Sum" &&
                            alarm.Properties["Namespace"].Value <string>() == AwsNamespace.DynamoDb
                            )
                        );

            Assert.That(alarms.Exists(
                            alarm =>
                            alarm.Properties["MetricName"].Value <string>() == "ThrottledRequests" &&
                            alarm.Properties["AlarmName"].Value <string>().Contains("ThrottledRequestsHigh") &&
                            alarm.Properties["Threshold"].Value <int>() == defaultThrottleThreshold &&
                            alarm.Properties["Period"].Value <int>() == 60 &&
                            alarm.Properties["ComparisonOperator"].Value <string>() == "GreaterThanOrEqualToThreshold" &&
                            alarm.Properties["Statistic"].Value <string>() == "Sum" &&
                            alarm.Properties["Namespace"].Value <string>() == AwsNamespace.DynamoDb
                            )
                        );
        }