Repository: james-project Updated Branches: refs/heads/master b03574767 -> 0e437d259
http://git-wip-us.apache.org/repos/asf/james-project/blob/0e437d25/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/subscribers/QuotaThresholdNoticeTest.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/subscribers/QuotaThresholdNoticeTest.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/subscribers/QuotaThresholdNoticeTest.java new file mode 100644 index 0000000..e652e0b --- /dev/null +++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/subscribers/QuotaThresholdNoticeTest.java @@ -0,0 +1,202 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.mailbox.quota.mailing.subscribers; + +import static org.apache.james.mailbox.quota.model.HistoryEvolution.HighestThresholdRecentness.AlreadyReachedDuringGracePriod; +import static org.apache.james.mailbox.quota.model.HistoryEvolution.HighestThresholdRecentness.NotAlreadyReachedDuringGracePeriod; +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture.TestConstants.NOW; +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture._80; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Optional; + +import org.apache.james.mailbox.model.Quota; +import org.apache.james.mailbox.quota.QuotaCount; +import org.apache.james.mailbox.quota.QuotaSize; +import org.apache.james.mailbox.quota.model.HistoryEvolution; +import org.apache.james.mailbox.quota.model.QuotaThresholdChange; +import org.apache.james.mailbox.quota.model.QuotaThresholdFixture.Quotas.Counts; +import org.apache.james.mailbox.quota.model.QuotaThresholdFixture.Quotas.Sizes; +import org.junit.jupiter.api.Test; + +import nl.jqno.equalsverifier.EqualsVerifier; + +class QuotaThresholdNoticeTest { + + @Test + void shouldMatchBeanContract() { + EqualsVerifier.forClass(QuotaThresholdNotice.class) + .allFieldsShouldBeUsed() + .verify(); + } + + @Test + void buildShouldReturnEmptyWhenNoThresholds() { + assertThat(QuotaThresholdNotice.builder() + .sizeQuota(Sizes._82_PERCENT) + .countQuota(Counts._82_PERCENT) + .build()) + .isEmpty(); + } + + @Test + void buildShouldReturnEmptyWhenNoChanges() { + assertThat(QuotaThresholdNotice.builder() + .sizeQuota(Sizes._82_PERCENT) + .countQuota(Counts._82_PERCENT) + .sizeThreshold(HistoryEvolution.noChanges()) + .build()) + .isEmpty(); + } + + @Test + void buildShouldReturnEmptyWhenBelow() { + assertThat(QuotaThresholdNotice.builder() + .sizeQuota(Sizes._82_PERCENT) + .countQuota(Counts._82_PERCENT) + .sizeThreshold(HistoryEvolution.lowerThresholdReached(new QuotaThresholdChange(_80, NOW))) + .build()) + .isEmpty(); + } + + @Test + void buildShouldReturnEmptyWhenAboveButRecentChanges() { + assertThat(QuotaThresholdNotice.builder() + .sizeQuota(Sizes._82_PERCENT) + .countQuota(Counts._82_PERCENT) + .sizeThreshold(HistoryEvolution.higherThresholdReached(new QuotaThresholdChange(_80, NOW), AlreadyReachedDuringGracePriod)) + .build()) + .isEmpty(); + } + + @Test + void buildShouldReturnPresentWhenAbove() { + Quota<QuotaSize> sizeQuota = Sizes._82_PERCENT; + Quota<QuotaCount> countQuota = Counts._82_PERCENT; + QuotaThresholdChange sizeThresholdChange = new QuotaThresholdChange(_80, NOW); + + assertThat(QuotaThresholdNotice.builder() + .sizeQuota(sizeQuota) + .countQuota(countQuota) + .sizeThreshold(HistoryEvolution.higherThresholdReached(sizeThresholdChange, NotAlreadyReachedDuringGracePeriod)) + .build()) + .isNotEmpty() + .contains(new QuotaThresholdNotice(Optional.empty(), Optional.of(sizeThresholdChange.getQuotaThreshold()), sizeQuota, countQuota)); + } + + @Test + void buildShouldFilterOutNotInterestingFields() { + Quota<QuotaSize> sizeQuota = Sizes._82_PERCENT; + Quota<QuotaCount> countQuota = Counts._82_PERCENT; + QuotaThresholdChange sizeThresholdChange = new QuotaThresholdChange(_80, NOW); + QuotaThresholdChange countThresholdChange = new QuotaThresholdChange(_80, NOW); + + assertThat(QuotaThresholdNotice.builder() + .sizeQuota(sizeQuota) + .countQuota(countQuota) + .sizeThreshold(HistoryEvolution.higherThresholdReached(sizeThresholdChange, NotAlreadyReachedDuringGracePeriod)) + .countThreshold(HistoryEvolution.lowerThresholdReached(countThresholdChange)) + .build()) + .isNotEmpty() + .contains(new QuotaThresholdNotice(Optional.empty(), Optional.of(sizeThresholdChange.getQuotaThreshold()), sizeQuota, countQuota)); + } + + @Test + void buildShouldKeepAllInterestingFields() { + Quota<QuotaSize> sizeQuota = Sizes._82_PERCENT; + Quota<QuotaCount> countQuota = Counts._82_PERCENT; + QuotaThresholdChange sizeThresholdChange = new QuotaThresholdChange(_80, NOW); + QuotaThresholdChange countThresholdChange = new QuotaThresholdChange(_80, NOW); + + assertThat(QuotaThresholdNotice.builder() + .sizeQuota(sizeQuota) + .countQuota(countQuota) + .sizeThreshold(HistoryEvolution.higherThresholdReached(sizeThresholdChange, NotAlreadyReachedDuringGracePeriod)) + .countThreshold(HistoryEvolution.higherThresholdReached(countThresholdChange, NotAlreadyReachedDuringGracePeriod)) + .build()) + .isNotEmpty() + .contains(new QuotaThresholdNotice(Optional.of(countThresholdChange.getQuotaThreshold()), Optional.of(sizeThresholdChange.getQuotaThreshold()), sizeQuota, countQuota)); + } + + @Test + void generateReportShouldGenerateAHumanReadableMessage() { + QuotaThresholdChange sizeThresholdChange = new QuotaThresholdChange(_80, NOW); + QuotaThresholdChange countThresholdChange = new QuotaThresholdChange(_80, NOW); + + assertThat(QuotaThresholdNotice.builder() + .sizeQuota(Sizes._82_PERCENT) + .countQuota(Counts._92_PERCENT) + .sizeThreshold(HistoryEvolution.higherThresholdReached(sizeThresholdChange, NotAlreadyReachedDuringGracePeriod)) + .countThreshold(HistoryEvolution.higherThresholdReached(countThresholdChange, NotAlreadyReachedDuringGracePeriod)) + .build() + .get() + .generateReport()) + .isEqualTo("You receive this email because you recently exceeded a threshold related to the quotas of your email account.\n" + + "\n" + + "You currently occupy more than 80 % of the total size allocated to you.\n" + + "You currently occupy 82 bytes on a total of 100 bytes allocated to you.\n" + + "\n" + + "You currently occupy more than 80 % of the total message count allocated to you.\n" + + "You currently have 92 messages on a total of 100 allowed for you.\n" + + "\n" + + "You need to be aware that actions leading to exceeded quotas will be denied. This will result in a degraded service.\n" + + "To mitigate this issue you might reach your administrator in order to increase your configured quota. You might also delete some non important emails."); + } + + @Test + void generateReportShouldOmitCountPartWhenNone() { + QuotaThresholdChange sizeThresholdChange = new QuotaThresholdChange(_80, NOW); + + assertThat(QuotaThresholdNotice.builder() + .sizeQuota(Sizes._82_PERCENT) + .countQuota(Counts._72_PERCENT) + .sizeThreshold(HistoryEvolution.higherThresholdReached(sizeThresholdChange, NotAlreadyReachedDuringGracePeriod)) + .build() + .get() + .generateReport()) + .isEqualTo("You receive this email because you recently exceeded a threshold related to the quotas of your email account.\n" + + "\n" + + "You currently occupy more than 80 % of the total size allocated to you.\n" + + "You currently occupy 82 bytes on a total of 100 bytes allocated to you.\n" + + "\n" + + "You need to be aware that actions leading to exceeded quotas will be denied. This will result in a degraded service.\n" + + "To mitigate this issue you might reach your administrator in order to increase your configured quota. You might also delete some non important emails."); + } + + @Test + void generateReportShouldOmitSizePartWhenNone() { + QuotaThresholdChange countThresholdChange = new QuotaThresholdChange(_80, NOW); + + assertThat(QuotaThresholdNotice.builder() + .sizeQuota(Sizes._82_PERCENT) + .countQuota(Counts._92_PERCENT) + .countThreshold(HistoryEvolution.higherThresholdReached(countThresholdChange, NotAlreadyReachedDuringGracePeriod)) + .build() + .get() + .generateReport()) + .isEqualTo("You receive this email because you recently exceeded a threshold related to the quotas of your email account.\n" + + "\n" + + "You currently occupy more than 80 % of the total message count allocated to you.\n" + + "You currently have 92 messages on a total of 100 allowed for you.\n" + + "\n" + + "You need to be aware that actions leading to exceeded quotas will be denied. This will result in a degraded service.\n" + + "To mitigate this issue you might reach your administrator in order to increase your configured quota. You might also delete some non important emails."); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/0e437d25/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/HistoryEvolutionTest.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/HistoryEvolutionTest.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/HistoryEvolutionTest.java new file mode 100644 index 0000000..566991c --- /dev/null +++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/HistoryEvolutionTest.java @@ -0,0 +1,104 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.mailbox.quota.model; + +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture.TestConstants.NOW; +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture._75; +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +import nl.jqno.equalsverifier.EqualsVerifier; + +class HistoryEvolutionTest { + + private static final QuotaThresholdChange SAMPLE_THRESHOLD = new QuotaThresholdChange(_75, NOW); + + @Test + void shouldMatchBeanContract() { + EqualsVerifier.forClass(HistoryEvolution.class) + .allFieldsShouldBeUsed() + .verify(); + } + + @Test + void isModifiedShouldReturnFalseWhenNoChange() { + assertThat( + HistoryEvolution.noChanges() + .isChange()) + .isFalse(); + } + + @Test + void isModifiedShouldReturnTrueWhenLowerThresholdReached() { + assertThat( + HistoryEvolution.lowerThresholdReached(SAMPLE_THRESHOLD) + .isChange()) + .isTrue(); + } + + @Test + void isModifiedShouldReturnTrueWhenHigherThresholdAlreadyReachedWithinGracePeriod() { + assertThat( + HistoryEvolution.higherThresholdReached(SAMPLE_THRESHOLD, HistoryEvolution.HighestThresholdRecentness.AlreadyReachedDuringGracePriod) + .isChange()) + .isTrue(); + } + + @Test + void isModifiedShouldReturnTrueWhenHigherThresholdReachedNotAlreadyReachedWithinGracePeriod() { + assertThat( + HistoryEvolution.higherThresholdReached(SAMPLE_THRESHOLD, HistoryEvolution.HighestThresholdRecentness.NotAlreadyReachedDuringGracePeriod) + .isChange()) + .isTrue(); + } + + @Test + void currentThresholdNotRecentlyReachedShouldReturnFalseWhenNoChange() { + assertThat( + HistoryEvolution.noChanges() + .currentThresholdNotRecentlyReached()) + .isFalse(); + } + + @Test + void currentThresholdNotRecentlyReachedShouldReturnFalseWhenLowerThresholdReached() { + assertThat( + HistoryEvolution.lowerThresholdReached(SAMPLE_THRESHOLD) + .currentThresholdNotRecentlyReached()) + .isFalse(); + } + + @Test + void currentThresholdNotRecentlyReachedShouldReturnFalseWhenHigherThresholdReachedAlreadyReachedWithinGracePeriod() { + assertThat( + HistoryEvolution.higherThresholdReached(SAMPLE_THRESHOLD, HistoryEvolution.HighestThresholdRecentness.AlreadyReachedDuringGracePriod) + .currentThresholdNotRecentlyReached()) + .isFalse(); + } + + @Test + void currentThresholdNotRecentlyReachedShouldReturnTrueWhenHigherThresholdReachedNotAlreadyReachedWithinGracePeriod() { + assertThat( + HistoryEvolution.higherThresholdReached(SAMPLE_THRESHOLD, HistoryEvolution.HighestThresholdRecentness.NotAlreadyReachedDuringGracePeriod) + .currentThresholdNotRecentlyReached()) + .isTrue(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/0e437d25/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdChangeTest.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdChangeTest.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdChangeTest.java new file mode 100644 index 0000000..5fb150e --- /dev/null +++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdChangeTest.java @@ -0,0 +1,59 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.mailbox.quota.model; + +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture.TestConstants.ONE_HOUR_AGO; +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture.TestConstants.THREE_HOURS_AGO; +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture.TestConstants.TWO_HOURS_AGO; +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture._75; +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +import nl.jqno.equalsverifier.EqualsVerifier; + +class QuotaThresholdChangeTest { + @Test + void shouldMatchBeanContract() { + EqualsVerifier.forClass(QuotaThresholdChange.class) + .allFieldsShouldBeUsed() + .verify(); + } + + @Test + void isAfterShouldReturnTrueWhenRecent() { + QuotaThresholdChange change = new QuotaThresholdChange(_75, TWO_HOURS_AGO); + assertThat(change.isAfter(THREE_HOURS_AGO)).isTrue(); + } + + @Test + void isAfterShouldReturnFalseWhenOld() { + QuotaThresholdChange change = new QuotaThresholdChange(_75, TWO_HOURS_AGO); + + assertThat(change.isAfter(ONE_HOUR_AGO)).isFalse(); + } + + @Test + void isAfterShouldReturnFalseWhenSameInstant() { + QuotaThresholdChange change = new QuotaThresholdChange(_75, TWO_HOURS_AGO); + + assertThat(change.isAfter(TWO_HOURS_AGO)).isFalse(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/0e437d25/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdFixture.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdFixture.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdFixture.java new file mode 100644 index 0000000..1770420 --- /dev/null +++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdFixture.java @@ -0,0 +1,149 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.mailbox.quota.model; + +import java.time.Duration; +import java.time.Instant; +import java.util.Optional; + +import org.apache.james.mailbox.mock.MockMailboxSession; +import org.apache.james.mailbox.model.Quota; +import org.apache.james.mailbox.model.QuotaRoot; +import org.apache.james.mailbox.quota.QuotaCount; +import org.apache.james.mailbox.quota.QuotaSize; +import org.apache.james.mailbox.quota.mailing.QuotaMailingListenerConfiguration; +import org.apache.mailet.base.MailAddressFixture; +import org.apache.mailet.base.test.FakeMailContext; + +import com.google.common.collect.ImmutableList; + +public interface QuotaThresholdFixture { + QuotaThreshold _50 = new QuotaThreshold(0.50); + QuotaThreshold _75 = new QuotaThreshold(0.75); + QuotaThreshold _759 = new QuotaThreshold(0.759); + QuotaThreshold _80 = new QuotaThreshold(0.8); + QuotaThreshold _90 = new QuotaThreshold(0.9); + QuotaThreshold _95 = new QuotaThreshold(0.95); + QuotaThreshold _99 = new QuotaThreshold(0.99); + + interface Quotas { + interface Counts { + Quota<QuotaCount> _32_PERCENT = Quota.<QuotaCount>builder() + .used(QuotaCount.count(32)) + .computedLimit(QuotaCount.count(100)) + .build(); + + Quota<QuotaCount> _40_PERCENT = Quota.<QuotaCount>builder() + .used(QuotaCount.count(40)) + .computedLimit(QuotaCount.count(100)) + .build(); + + Quota<QuotaCount> _52_PERCENT = Quota.<QuotaCount>builder() + .used(QuotaCount.count(52)) + .computedLimit(QuotaCount.count(100)) + .build(); + + Quota<QuotaCount> _72_PERCENT = Quota.<QuotaCount>builder() + .used(QuotaCount.count(72)) + .computedLimit(QuotaCount.count(100)) + .build(); + + Quota<QuotaCount> _82_PERCENT = Quota.<QuotaCount>builder() + .used(QuotaCount.count(82)) + .computedLimit(QuotaCount.count(100)) + .build(); + + Quota<QuotaCount> _85_PERCENT = Quota.<QuotaCount>builder() + .used(QuotaCount.count(85)) + .computedLimit(QuotaCount.count(100)) + .build(); + + Quota<QuotaCount> _92_PERCENT = Quota.<QuotaCount>builder() + .used(QuotaCount.count(92)) + .computedLimit(QuotaCount.count(100)) + .build(); + } + interface Sizes { + Quota<QuotaSize> _30_PERCENT = Quota.<QuotaSize>builder() + .used(QuotaSize.size(30)) + .computedLimit(QuotaSize.size(100)) + .build(); + Quota<QuotaSize> _42_PERCENT = Quota.<QuotaSize>builder() + .used(QuotaSize.size(42)) + .computedLimit(QuotaSize.size(100)) + .build(); + + Quota<QuotaSize> _55_PERCENT = Quota.<QuotaSize>builder() + .used(QuotaSize.size(55)) + .computedLimit(QuotaSize.size(100)) + .build(); + + Quota<QuotaSize> _60_PERCENT = Quota.<QuotaSize>builder() + .used(QuotaSize.size(60)) + .computedLimit(QuotaSize.size(100)) + .build(); + + Quota<QuotaSize> _75_PERCENT = Quota.<QuotaSize>builder() + .used(QuotaSize.size(75)) + .computedLimit(QuotaSize.size(100)) + .build(); + + Quota<QuotaSize> _82_PERCENT = Quota.<QuotaSize>builder() + .used(QuotaSize.size(82)) + .computedLimit(QuotaSize.size(100)) + .build(); + + Quota<QuotaSize> _92_PERCENT = Quota.<QuotaSize>builder() + .used(QuotaSize.size(92)) + .computedLimit(QuotaSize.size(100)) + .build(); + + Quota<QuotaSize> _992_PERTHOUSAND = Quota.<QuotaSize>builder() + .used(QuotaSize.size(992)) + .computedLimit(QuotaSize.size(1000)) + .build(); + } + } + + interface TestConstants { + Duration GRACE_PERIOD = Duration.ofDays(1); + QuotaThresholds SINGLE_THRESHOLD = new QuotaThresholds(ImmutableList.of(_50)); + QuotaMailingListenerConfiguration DEFAULT_CONFIGURATION = new QuotaMailingListenerConfiguration(SINGLE_THRESHOLD, GRACE_PERIOD); + String BOB = "bob@domain"; + MockMailboxSession BOB_SESSION = new MockMailboxSession(BOB); + Instant NOW = Instant.now(); + QuotaRoot QUOTAROOT = QuotaRoot.quotaRoot("any", Optional.empty()); + Instant ONE_HOUR_AGO = NOW.minus(Duration.ofHours(1)); + Instant TWO_HOURS_AGO = NOW.minus(Duration.ofHours(2)); + Instant THREE_HOURS_AGO = NOW.minus(Duration.ofHours(3)); + Instant SIX_HOURS_AGO = NOW.minus(Duration.ofHours(6)); + Instant TWELVE_HOURS_AGO = NOW.minus(Duration.ofHours(12)); + Instant TWO_DAYS_AGO = NOW.minus(Duration.ofDays(2)); + Instant SIX_DAYS_AGO = NOW.minus(Duration.ofDays(6)); + Instant TWELVE_DAYS_AGO = NOW.minus(Duration.ofDays(12)); + } + + static FakeMailContext mailetContext() { + return FakeMailContext.builder() + .postmaster(MailAddressFixture.POSTMASTER_AT_JAMES) + .build(); + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/0e437d25/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdHistoryTest.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdHistoryTest.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdHistoryTest.java new file mode 100644 index 0000000..9ea774d --- /dev/null +++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdHistoryTest.java @@ -0,0 +1,87 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.mailbox.quota.model; + +import static org.apache.james.mailbox.quota.model.HistoryEvolution.HighestThresholdRecentness.AlreadyReachedDuringGracePriod; +import static org.apache.james.mailbox.quota.model.HistoryEvolution.HighestThresholdRecentness.NotAlreadyReachedDuringGracePeriod; +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture.TestConstants.GRACE_PERIOD; +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture.TestConstants.NOW; +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture._50; +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture._75; +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Duration; + +import org.junit.jupiter.api.Test; + +import nl.jqno.equalsverifier.EqualsVerifier; + +public class QuotaThresholdHistoryTest { + + @Test + public void shouldMatchBeanContract() { + EqualsVerifier.forClass(QuotaThresholdHistory.class) + .allFieldsShouldBeUsed() + .verify(); + } + + @Test + public void compareWithCurrentThresholdShouldReturnAboveWhenStrictlyAboveDuringDuration() { + assertThat( + new QuotaThresholdHistory( + new QuotaThresholdChange(_50, NOW.minus(Duration.ofDays(24))), + new QuotaThresholdChange(_75, NOW.minus(Duration.ofDays(12))), + new QuotaThresholdChange(_50, NOW.minus(Duration.ofDays(6)))) + .compareWithCurrentThreshold(new QuotaThresholdChange(_75, NOW), GRACE_PERIOD)) + .isEqualTo(HistoryEvolution.higherThresholdReached(new QuotaThresholdChange(_75, NOW), NotAlreadyReachedDuringGracePeriod)); + } + + @Test + public void compareWithCurrentThresholdShouldReturnBelowWhenLowerThanLastChange() { + assertThat( + new QuotaThresholdHistory( + new QuotaThresholdChange(_50, NOW.minus(Duration.ofDays(24))), + new QuotaThresholdChange(_75, NOW.minus(Duration.ofDays(12)))) + .compareWithCurrentThreshold(new QuotaThresholdChange(_50, NOW), GRACE_PERIOD)) + .isEqualTo(HistoryEvolution.lowerThresholdReached(new QuotaThresholdChange(_50, NOW))); + } + + @Test + public void compareWithCurrentThresholdShouldReturnNoChangeWhenEqualsLastChange() { + assertThat( + new QuotaThresholdHistory( + new QuotaThresholdChange(_50, NOW.minus(Duration.ofDays(24))), + new QuotaThresholdChange(_75, NOW.minus(Duration.ofDays(12)))) + .compareWithCurrentThreshold(new QuotaThresholdChange(_75, NOW), GRACE_PERIOD)) + .isEqualTo(HistoryEvolution.noChanges()); + } + + @Test + public void compareWithCurrentThresholdShouldReturnAboveWithRecentChangesWhenThresholdExceededDuringDuration() { + assertThat( + new QuotaThresholdHistory( + new QuotaThresholdChange(_50, NOW.minus(Duration.ofDays(24))), + new QuotaThresholdChange(_75, NOW.minus(Duration.ofHours(12))), + new QuotaThresholdChange(_50, NOW.minus(Duration.ofHours(6)))) + .compareWithCurrentThreshold(new QuotaThresholdChange(_75, NOW), GRACE_PERIOD)) + .isEqualTo(HistoryEvolution.higherThresholdReached(new QuotaThresholdChange(_75, NOW), AlreadyReachedDuringGracePriod)); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/0e437d25/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdTest.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdTest.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdTest.java new file mode 100644 index 0000000..f46eb38 --- /dev/null +++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdTest.java @@ -0,0 +1,141 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.mailbox.quota.model; + +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture._75; +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture._759; +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture._90; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.apache.james.mailbox.model.Quota; +import org.apache.james.mailbox.quota.QuotaSize; +import org.apache.james.mailbox.quota.model.QuotaThresholdFixture.Quotas.Sizes; +import org.junit.jupiter.api.Test; + +import nl.jqno.equalsverifier.EqualsVerifier; + +public class QuotaThresholdTest { + + @Test + public void shouldMatchBeanContract() { + EqualsVerifier.forClass(QuotaThreshold.class) + .allFieldsShouldBeUsed() + .verify(); + } + + @Test + public void constructorShouldThrowBelowLowerValue() { + assertThatThrownBy(() -> new QuotaThreshold(-0.00001)) + .isInstanceOf(IllegalArgumentException.class); + } + + + @Test + public void constructorShouldThrowAboveUpperValue() { + assertThatThrownBy(() -> new QuotaThreshold(1.00001)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void constructorShouldNotThrowOnLowerValue() { + assertThatCode(() -> new QuotaThreshold(0.)) + .doesNotThrowAnyException(); + } + + @Test + public void constructorShouldNotThrowOnUpperValue() { + assertThatCode(() -> new QuotaThreshold(1.)) + .doesNotThrowAnyException(); + } + + @Test + public void isExceededShouldReturnFalseWhenBelowThreshold() { + assertThat(_75.isExceeded(Sizes._60_PERCENT)) + .isFalse(); + } + + @Test + public void isExceededShouldReturnTrueWhenAboveThreshold() { + assertThat(_75.isExceeded(Sizes._82_PERCENT)) + .isTrue(); + } + + @Test + public void isExceededShouldReturnFalseWhenOnThreshold() { + assertThat(_75.isExceeded(Sizes._75_PERCENT)) + .isFalse(); + } + + @Test + public void isExceededShouldReturnFalseWhenUnlimited() { + Quota<QuotaSize> quota = Quota.<QuotaSize>builder() + .computedLimit(QuotaSize.unlimited()) + .used(QuotaSize.size(80)) + .build(); + + assertThat(_75.isExceeded(quota)) + .isFalse(); + } + + @Test + public void nonZeroShouldFilterZero() { + assertThat(QuotaThreshold.ZERO.nonZero()) + .isEmpty(); + } + + @Test + public void nonZeroShouldNotFilterNonZeroValues() { + assertThat(_75.nonZero()) + .contains(_75); + } + + @Test + public void getQuotaOccupationRatioAsPercentShouldReturnIntRepresentationOfThreshold() { + assertThat(_75.getQuotaOccupationRatioAsPercent()) + .isEqualTo(75); + } + + @Test + public void getQuotaOccupationRatioAsPercentShouldTruncateValues() { + assertThat(_759.getQuotaOccupationRatioAsPercent()) + .isEqualTo(75); + } + + @Test + public void compareToShouldReturnNegativeWhenLowerThanComparedValue() { + assertThat(_75.compareTo(_90)) + .isLessThan(0); + } + + @Test + public void compareToShouldReturnPositiveWhenHigherThanComparedValue() { + assertThat(_90.compareTo(_75)) + .isGreaterThan(0); + } + + @Test + public void compareToShouldReturnZeroWhenEquals() { + assertThat(_75.compareTo(_75)) + .isEqualTo(0); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/0e437d25/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdsTest.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdsTest.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdsTest.java new file mode 100644 index 0000000..09245eb --- /dev/null +++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/model/QuotaThresholdsTest.java @@ -0,0 +1,83 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.mailbox.quota.model; + +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture._50; +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture._80; +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture._95; +import static org.apache.james.mailbox.quota.model.QuotaThresholdFixture._99; +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.james.mailbox.model.Quota; +import org.apache.james.mailbox.quota.QuotaSize; +import org.apache.james.mailbox.quota.model.QuotaThresholdFixture.Quotas.Sizes; +import org.junit.jupiter.api.Test; + +import com.google.common.collect.ImmutableList; + +public class QuotaThresholdsTest { + + @Test + public void highestExceededThresholdShouldReturnZeroWhenBelowAllThresholds() { + assertThat( + new QuotaThresholds(ImmutableList.of(_50, _80, _95, _99)) + .highestExceededThreshold(Quota.<QuotaSize>builder() + .used(QuotaSize.size(40)) + .computedLimit(QuotaSize.size(100)) + .build())) + .isEqualTo(QuotaThreshold.ZERO); + } + + @Test + public void highestExceededThresholdShouldReturnHighestExceededThreshold() { + assertThat( + new QuotaThresholds(ImmutableList.of(_50, _80, _95, _99)) + .highestExceededThreshold(Sizes._92_PERCENT)) + .isEqualTo(_80); + } + + @Test + public void highestExceededThresholdShouldReturnHighestThresholdWhenAboveAllThresholds() { + assertThat( + new QuotaThresholds(ImmutableList.of(_50, _80, _95, _99)) + .highestExceededThreshold(Sizes._992_PERTHOUSAND)) + .isEqualTo(_99); + } + + @Test + public void highestExceededThresholdShouldReturnZeroWhenNoThresholds() { + assertThat( + new QuotaThresholds(ImmutableList.of()) + .highestExceededThreshold(Sizes._992_PERTHOUSAND)) + .isEqualTo(QuotaThreshold.ZERO); + } + + @Test + public void highestExceededThresholdShouldReturnZeroWhenUnlimitedQuota() { + assertThat( + new QuotaThresholds(ImmutableList.of(_50, _80, _95, _99)) + .highestExceededThreshold(Quota.<QuotaSize>builder() + .used(QuotaSize.size(992)) + .computedLimit(QuotaSize.unlimited()) + .build())) + .isEqualTo(QuotaThreshold.ZERO); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/0e437d25/mailbox/pom.xml ---------------------------------------------------------------------- diff --git a/mailbox/pom.xml b/mailbox/pom.xml index a8204d2..560d59b 100644 --- a/mailbox/pom.xml +++ b/mailbox/pom.xml @@ -53,6 +53,8 @@ <module>tool</module> <module>zoo-seq-provider</module> + <module>plugin/quota-mailing</module> + <module>plugin/quota-mailing-memory</module> <module>plugin/spamassassin</module> </modules> http://git-wip-us.apache.org/repos/asf/james-project/blob/0e437d25/mailbox/store/src/main/java/org/apache/james/mailbox/store/event/MailboxEventDispatcher.java ---------------------------------------------------------------------- diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/event/MailboxEventDispatcher.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/event/MailboxEventDispatcher.java index 37779cb..80dcc18 100644 --- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/event/MailboxEventDispatcher.java +++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/event/MailboxEventDispatcher.java @@ -19,12 +19,14 @@ package org.apache.james.mailbox.store.event; +import java.time.Instant; import java.util.List; import java.util.Map; import java.util.SortedMap; import javax.inject.Inject; +import org.apache.james.mailbox.Event; import org.apache.james.mailbox.MailboxListener; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageUid; @@ -167,6 +169,10 @@ public class MailboxEventDispatcher { } public void quota(MailboxSession session, QuotaRoot quotaRoot, Quota<QuotaCount> countQuota, Quota<QuotaSize> sizeQuota) { - listener.event(new MailboxListener.QuotaUsageUpdatedEvent(session, quotaRoot, countQuota, sizeQuota)); + listener.event(new MailboxListener.QuotaUsageUpdatedEvent(session, quotaRoot, countQuota, sizeQuota, Instant.now())); + } + + public void event(Event event) { + listener.event(event); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/0e437d25/mailet/base/src/test/java/org/apache/mailet/base/MailAddressFixture.java ---------------------------------------------------------------------- diff --git a/mailet/base/src/test/java/org/apache/mailet/base/MailAddressFixture.java b/mailet/base/src/test/java/org/apache/mailet/base/MailAddressFixture.java index fed98ba..24ebc74 100644 --- a/mailet/base/src/test/java/org/apache/mailet/base/MailAddressFixture.java +++ b/mailet/base/src/test/java/org/apache/mailet/base/MailAddressFixture.java @@ -38,6 +38,7 @@ public class MailAddressFixture { public static final MailAddress ANY_AT_LOCAL = createMailAddress("any@" + JAMES_LOCAL); public static final MailAddress OTHER_AT_LOCAL = createMailAddress("other@" + JAMES_LOCAL); public static final MailAddress ANY_AT_JAMES = createMailAddress("any@" + JAMES_APACHE_ORG); + public static final MailAddress POSTMASTER_AT_JAMES = createMailAddress("postmaster@" + JAMES_APACHE_ORG); public static final MailAddress OTHER_AT_JAMES = createMailAddress("other@" + JAMES_APACHE_ORG); public static final MailAddress ANY_AT_JAMES2 = createMailAddress("any@" + JAMES2_APACHE_ORG); public static final MailAddress OTHER_AT_JAMES2 = createMailAddress("other@" + JAMES2_APACHE_ORG); http://git-wip-us.apache.org/repos/asf/james-project/blob/0e437d25/mailet/base/src/test/java/org/apache/mailet/base/test/FakeMailContext.java ---------------------------------------------------------------------- diff --git a/mailet/base/src/test/java/org/apache/mailet/base/test/FakeMailContext.java b/mailet/base/src/test/java/org/apache/mailet/base/test/FakeMailContext.java index 687b996..eff41c9 100644 --- a/mailet/base/src/test/java/org/apache/mailet/base/test/FakeMailContext.java +++ b/mailet/base/src/test/java/org/apache/mailet/base/test/FakeMailContext.java @@ -20,7 +20,6 @@ package org.apache.mailet.base.test; import java.io.Serializable; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; @@ -28,6 +27,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.TimeUnit; import javax.mail.MessagingException; @@ -365,15 +365,15 @@ public class FakeMailContext implements MailetContext { } private final HashMap<String, Object> attributes; - private final List<SentMail> sentMails; - private final List<BouncedMail> bouncedMails; + private final Collection<SentMail> sentMails; + private final Collection<BouncedMail> bouncedMails; private final Optional<Logger> logger; private final MailAddress postmaster; private FakeMailContext(Optional<Logger> logger, MailAddress postmaster) { attributes = new HashMap<>(); - sentMails = new ArrayList<>(); - bouncedMails = new ArrayList<>(); + sentMails = new ConcurrentLinkedQueue<>(); + bouncedMails = new ConcurrentLinkedQueue<>(); this.logger = logger; this.postmaster = postmaster; } @@ -590,11 +590,15 @@ public class FakeMailContext implements MailetContext { } public List<SentMail> getSentMails() { - return sentMails; + return ImmutableList.copyOf(sentMails); + } + + public void resetSentMails() { + sentMails.clear(); } public List<BouncedMail> getBouncedMails() { - return bouncedMails; + return ImmutableList.copyOf(bouncedMails); } @Override http://git-wip-us.apache.org/repos/asf/james-project/blob/0e437d25/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 9c296f1..9ba6851 100644 --- a/pom.xml +++ b/pom.xml @@ -824,6 +824,17 @@ </dependency> <dependency> <groupId>${project.groupId}</groupId> + <artifactId>apache-james-mailbox-quota-mailing</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>apache-james-mailbox-quota-mailing</artifactId> + <type>test-jar</type> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> <artifactId>apache-james-mailbox-spring</artifactId> <version>${project.version}</version> </dependency> --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org