public async Task ShouldHandleChangeSaveAndDispatchWhenMxRecordsPolledReceived() { string snsTopicArn = "SnsTopicArn"; A.CallTo(() => _mxEntityConfig.SnsTopicArn).Returns(snsTopicArn); string domainName = "testDomainName"; MxEntityState stateFromDb = new MxEntityState(domainName.ToLower()) { MxState = MxState.Created }; A.CallTo(() => _dao.Get(domainName.ToLower())).Returns(Task.FromResult(stateFromDb)); A.CallTo(() => _mxEntityConfig.NextScheduledInSeconds).Returns(33); A.CallTo(() => _clock.GetDateTimeUtc()).Returns(DateTime.MinValue); MxRecordsPolled message = new MxRecordsPolled(domainName, new List <HostMxRecord>(), null) { Timestamp = DateTime.UnixEpoch }; await _mxEntity.Handle(message); Assert.AreEqual(stateFromDb.MxState, MxState.Evaluated); Assert.AreEqual(stateFromDb.HostMxRecords, message.Records); Assert.AreEqual(stateFromDb.LastUpdated, message.Timestamp); A.CallTo(() => _changeNotifiersComposite.Handle(stateFromDb, message)).MustHaveHappenedOnceExactly(); A.CallTo(() => _dao.Save(stateFromDb)).MustHaveHappenedOnceExactly(); A.CallTo(() => _dispatcher.Dispatch(A <MxRecordsUpdated> .That.Matches(a => a.Id == message.Id.ToLower() && a.Records.Count == 0), snsTopicArn)).MustHaveHappenedOnceExactly(); A.CallTo(() => _dispatcher.Dispatch(A <CreateScheduledReminder> .That.Matches(a => a.ResourceId == domainName.ToLower() && a.Service == "Mx" && a.ScheduledTime.Second == 33), snsTopicArn)).MustHaveHappenedOnceExactly(); }
public void DoesNotNotifyWhenNoChangesWithDifferentCaseType() { string testDomain = "domain"; MxEntityState state = new MxEntityState(testDomain) { HostMxRecords = new List <HostMxRecord> { new HostMxRecord("HOSTNAME", 5, new List <string> { "192.168.0.1" }) } }; List <HostMxRecord> hostMxRecords = new List <HostMxRecord> { new HostMxRecord("hostname", 5, new List <string> { "192.168.0.1" }) }; MxRecordsPolled mxRecordsPolled = new MxRecordsPolled(testDomain, hostMxRecords, TimeSpan.MinValue); _recordChangedNotifier.Handle(state, mxRecordsPolled); A.CallTo(() => _dispatcher.Dispatch(A <MxRecordAdded> ._, A <string> ._)).MustNotHaveHappened(); A.CallTo(() => _dispatcher.Dispatch(A <MxRecordRemoved> ._, A <string> ._)).MustNotHaveHappened(); }
public void DoesNotNotifyWhenNoChanges() { string testDomain = "domain"; string testHostName = "hostname"; MxEntityState state = new MxEntityState(testDomain); HostMxRecord record = new HostMxRecord(testHostName, 5, new List <string> { "192.168.0.1", "192.168.0.2" }); state.HostMxRecords = new List <HostMxRecord> { new HostMxRecord(testHostName, 5, new List <string> { "192.168.0.1" }) }; List <HostMxRecord> hostMxRecords = new List <HostMxRecord> { record }; MxRecordsPolled mxRecordsPolled = new MxRecordsPolled(testDomain, hostMxRecords, TimeSpan.MinValue); _recordChangedNotifier.Handle(state, mxRecordsPolled); A.CallTo(() => _dispatcher.Dispatch(A <MxRecordAdded> ._, A <string> ._)).MustNotHaveHappened(); A.CallTo(() => _dispatcher.Dispatch(A <MxRecordRemoved> ._, A <string> ._)).MustNotHaveHappened(); }
public async Task Handle(MxRecordsPolled message) { string domainName = message.Id.ToLower(); MxEntityState state = await LoadState(domainName, nameof(message)); MxState oldState = state.MxState; int oldRecordCount = state.HostMxRecords?.Count ?? 0; int newRecordCount = message.Records?.Count ?? 0; _changeNotifiersComposite.Handle(state, message); List <HostMxRecord> validHostRecords = new List <HostMxRecord>(); if (message.Records != null) { foreach (HostMxRecord hostRecord in message.Records) { if (Uri.CheckHostName(hostRecord.Id) != UriHostNameType.Unknown) { validHostRecords.Add(hostRecord); } else { _log.LogInformation($"Erroneous host: {hostRecord.Id} found for domain: {domainName}"); } } } if (message.Error == null) { state.HostMxRecords = validHostRecords; } state.LastUpdated = message.Timestamp; state.Error = message.Error; state.MxState = MxState.Evaluated; await _dao.Save(state); _log.LogInformation($"Updated MxEntity from {oldState} to {MxState.Evaluated} and MX records before: {oldRecordCount} after: {newRecordCount} for {domainName}."); Message mxRecordsUpdated = new MxRecordsUpdated(domainName, validHostRecords); _dispatcher.Dispatch(mxRecordsUpdated, _mxEntityConfig.SnsTopicArn); _log.LogInformation($"An MxRecordsUpdated message for Domain: {domainName} has been dispatched to SnsTopic: {_mxEntityConfig.SnsTopicArn}"); // Should probably change this so it only happens for a new host validHostRecords?.ForEach(mxRecord => { _dispatcher.Dispatch(new MxHostTestPending(mxRecord.Id), _mxEntityConfig.SnsTopicArn); _log.LogInformation($"An MxHostTestPending message for Host: {mxRecord.Id} has been dispatched to SnsTopic: {_mxEntityConfig.SnsTopicArn}"); }); Message createScheduledReminder = new CreateScheduledReminder(Guid.NewGuid().ToString(), "Mx", domainName, _clock.GetDateTimeUtc().AddSeconds(_mxEntityConfig.NextScheduledInSeconds)); _dispatcher.Dispatch(createScheduledReminder, _mxEntityConfig.SnsTopicArn); _log.LogInformation($"A CreateScheduledReminder message for Domain: {domainName} has been dispatched to SnsTopic: {_mxEntityConfig.SnsTopicArn}"); }
public async Task ShouldOmitErroneousHostsFound() { string domainName = "test.gov.uk"; string hostName1 = "test-host-inbound1 .com"; string hostName2 = "test-host-inbound2.com"; string snsTopicArn = "SnsTopicArn"; A.CallTo(() => _mxEntityConfig.SnsTopicArn).Returns(snsTopicArn); List <HostMxRecord> hostMxRecords = new List <HostMxRecord> { new HostMxRecord(hostName1, 0, new List <string>()), new HostMxRecord(hostName2, 0, new List <string>()), }; MxEntityState stateFromDb = new MxEntityState(domainName.ToLower()) { MxState = MxState.Created, HostMxRecords = hostMxRecords, }; A.CallTo(() => _dao.Get(domainName.ToLower())).Returns(Task.FromResult(stateFromDb)); A.CallTo(() => _mxEntityConfig.NextScheduledInSeconds).Returns(33); A.CallTo(() => _clock.GetDateTimeUtc()).Returns(DateTime.MinValue); MxRecordsPolled message = new MxRecordsPolled(domainName, hostMxRecords, null) { Timestamp = DateTime.UnixEpoch }; List <HostMxRecord> validRecords = new List <HostMxRecord> { new HostMxRecord(hostName2, 0, new List <string>()) }; await _mxEntity.Handle(message); Assert.AreEqual(stateFromDb.MxState, MxState.Evaluated); Assert.AreEqual(stateFromDb.HostMxRecords[0], message.Records[1]); // Make sure erroneous host is ommitted Assert.AreEqual(stateFromDb.LastUpdated, message.Timestamp); A.CallTo(() => _changeNotifiersComposite.Handle(stateFromDb, message)).MustHaveHappenedOnceExactly(); A.CallTo(() => _dao.Save(stateFromDb)).MustHaveHappenedOnceExactly(); A.CallTo(() => _dispatcher.Dispatch(A <MxHostTestPending> .That.Matches(a => a.Id == hostName1.ToLower()), snsTopicArn)).MustNotHaveHappened(); A.CallTo(() => _dispatcher.Dispatch(A <MxHostTestPending> .That.Matches(a => a.Id == hostName2.ToLower()), snsTopicArn)).MustHaveHappenedOnceExactly(); }
public async Task Handle(MxPollPending message) { try { MxPollResult dmarcPollResult = await _processor.Process(message.Id); _log.LogInformation("Polled MX records for {Domain}", message.Id); MxRecordsPolled mxRecordsPolled = dmarcPollResult.ToMxRecordsPolled(); _dispatcher.Dispatch(mxRecordsPolled, _config.SnsTopicArn); _log.LogInformation("Published MX records for {Domain}", message.Id); } catch (System.Exception ex) { _log.LogError(ex, $"Error occurred polling domain {message.Id}"); throw; } }
public void NotifiesWhenRecordAddedAndRemoved() { string testDomain = "domain"; string testHostName1 = "hostname1"; string testHostName2 = "hostname2"; MxEntityState state = new MxEntityState(testDomain); HostMxRecord record1 = new HostMxRecord(testHostName1, 5, new List <string> { "192.168.0.1" }); HostMxRecord record2 = new HostMxRecord(testHostName2, 5, new List <string> { "192.168.0.1" }); state.HostMxRecords = new List <HostMxRecord> { record1 }; List <HostMxRecord> hostMxRecords = new List <HostMxRecord> { record2 }; MxRecordsPolled mxRecordsPolled = new MxRecordsPolled(testDomain, hostMxRecords, TimeSpan.MinValue); _recordChangedNotifier.Handle(state, mxRecordsPolled); A.CallTo(() => _dispatcher.Dispatch(A <MxRecordRemoved> ._, A <string> ._)) .MustHaveHappenedOnceExactly(); A.CallTo(() => _dispatcher.Dispatch( A <MxRecordRemoved> .That.Matches(x => x.Id == testDomain && x.Records[0].Id == testHostName1), A <string> ._)).MustHaveHappenedOnceExactly(); A.CallTo(() => _dispatcher.Dispatch(A <MxRecordAdded> ._, A <string> ._)) .MustHaveHappenedOnceExactly(); A.CallTo(() => _dispatcher.Dispatch( A <MxRecordAdded> .That.Matches(x => x.Id == testDomain && x.Records[0].Id == testHostName2), A <string> ._)).MustHaveHappenedOnceExactly(); }
public void NotifiesWhenMxPreferenceChanges() { string testDomain = "domain"; string testHostName = "hostname"; MxEntityState state = new MxEntityState(testDomain); state.HostMxRecords = new List <HostMxRecord> { new HostMxRecord(testHostName, 5, new List <string> { "192.168.0.1" }) }; List <HostMxRecord> hostMxRecords = new List <HostMxRecord> { new HostMxRecord(testHostName, 10, new List <string> { "192.168.0.1" }), }; MxRecordsPolled mxRecordsPolled = new MxRecordsPolled(testDomain, hostMxRecords, TimeSpan.MinValue); _recordChangedNotifier.Handle(state, mxRecordsPolled); A.CallTo(() => _dispatcher.Dispatch(A <MxRecordAdded> ._, A <string> ._)) .MustHaveHappenedOnceExactly(); A.CallTo(() => _dispatcher.Dispatch(A <MxRecordAdded> .That.Matches(x => x.Id == testDomain), A <string> ._)) .MustHaveHappenedOnceExactly(); A.CallTo(() => _dispatcher.Dispatch(A <MxRecordRemoved> ._, A <string> ._)) .MustHaveHappenedOnceExactly(); A.CallTo(() => _dispatcher.Dispatch(A <MxRecordRemoved> .That.Matches(x => x.Id == testDomain), A <string> ._)) .MustHaveHappenedOnceExactly(); }