4545import static com .tngtech .archunit .testutil .Assertions .assertThatRule ;
4646import static java .nio .file .Files .delete ;
4747import static java .nio .file .Files .exists ;
48+ import static java .nio .file .Files .readAllLines ;
4849import static java .util .stream .Collectors .toList ;
4950import static org .assertj .core .api .Assertions .assertThatThrownBy ;
5051
@@ -53,8 +54,11 @@ public class FreezingArchRuleTest {
5354
5455 private static final String STORE_PROPERTY_NAME = "freeze.store" ;
5556 private static final String STORE_DEFAULT_PATH_PROPERTY_NAME = "freeze.store.default.path" ;
57+ private static final String FREEZE_REFREEZE = "freeze.refreeze" ;
5658 private static final String ALLOW_STORE_CREATION_PROPERTY_NAME = "freeze.store.default.allowStoreCreation" ;
5759 private static final String ALLOW_STORE_UPDATE_PROPERTY_NAME = "freeze.store.default.allowStoreUpdate" ;
60+ private static final String DELETE_EMPTY_RULE_VIOLATION_PROPERTY_NAME = "freeze.store.default.deleteEmptyRuleViolation" ;
61+ private static final String WARN_EMPTY_RULE_VIOLATION_PROPERTY_NAME = "freeze.store.default.warnEmptyRuleViolation" ;
5862 private static final String LINE_MATCHER_PROPERTY_NAME = "freeze.lineMatcher" ;
5963
6064 @ Rule
@@ -152,13 +156,13 @@ public void allows_to_overwrite_frozen_violations_if_configured() {
152156 ArchRule anotherViolation = rule ("some description" ).withViolations ("first violation" , "second violation" ).create ();
153157 ArchRule frozenWithNewViolation = freeze (anotherViolation ).persistIn (violationStore );
154158
155- ArchConfiguration .get ().setProperty ("freeze.refreeze" , Boolean .TRUE .toString ());
159+ ArchConfiguration .get ().setProperty (FREEZE_REFREEZE , Boolean .TRUE .toString ());
156160
157161 assertThatRule (frozenWithNewViolation )
158162 .checking (importClasses (getClass ()))
159163 .hasNoViolation ();
160164
161- ArchConfiguration .get ().setProperty ("freeze.refreeze" , Boolean .FALSE .toString ());
165+ ArchConfiguration .get ().setProperty (FREEZE_REFREEZE , Boolean .FALSE .toString ());
162166
163167 assertThatRule (frozenWithNewViolation )
164168 .checking (importClasses (getClass ()))
@@ -482,6 +486,72 @@ public void can_prevent_default_ViolationStore_from_updating_existing_rules() th
482486 expectStoreUpdateDisabledException (() -> frozenRule .check (importClasses (getClass ())));
483487 }
484488
489+ @ Test
490+ public void warns_when_default_ViolationStore_is_empty () throws IOException {
491+ useTemporaryDefaultStorePath ();
492+ ArchConfiguration .get ().setProperty (ALLOW_STORE_CREATION_PROPERTY_NAME , "true" );
493+ ArchConfiguration .get ().setProperty (FREEZE_REFREEZE , "true" );
494+ FreezingArchRule frozenRule = freeze (rule ("some description" ).withoutViolations ().create ());
495+ frozenRule .check (importClasses (getClass ()));
496+
497+ // disallowing empty violation file should throw
498+ ArchConfiguration .get ().setProperty (WARN_EMPTY_RULE_VIOLATION_PROPERTY_NAME , "true" );
499+ assertThatThrownBy (() -> frozenRule .check (importClasses (getClass ())))
500+ .isInstanceOf (StoreEmptyException .class )
501+ .hasMessageContaining ("Saving empty violations for freezing rule is disabled (enable by configuration " + WARN_EMPTY_RULE_VIOLATION_PROPERTY_NAME + "=true)" );
502+ }
503+
504+ @ Test
505+ public void warns_when_default_ViolationStore_gets_empty () throws IOException {
506+ useTemporaryDefaultStorePath ();
507+ ArchConfiguration .get ().setProperty (ALLOW_STORE_CREATION_PROPERTY_NAME , "true" );
508+ RuleCreator someRule = rule ("some description" );
509+ freeze (someRule .withViolations ("remaining" , "will be solved" ).create ()).check (importClasses (getClass ()));
510+
511+ // disallowing empty violation file should throw
512+ ArchConfiguration .get ().setProperty (WARN_EMPTY_RULE_VIOLATION_PROPERTY_NAME , "true" );
513+ FreezingArchRule frozenRule = freeze (someRule .withoutViolations ().create ());
514+ assertThatThrownBy (() -> frozenRule .check (importClasses (getClass ())))
515+ .isInstanceOf (StoreEmptyException .class )
516+ .hasMessageContaining ("Saving empty violations for freezing rule is disabled (enable by configuration " + WARN_EMPTY_RULE_VIOLATION_PROPERTY_NAME + "=true)" );
517+ }
518+
519+ @ Test
520+ public void can_skip_default_ViolationStore_creation_for_empty_violations () throws IOException {
521+ File storeFolder = useTemporaryDefaultStorePath ();
522+ ArchConfiguration .get ().setProperty (STORE_PROPERTY_NAME , MyTextFileBasedViolationStore .class .getName ());
523+ ArchConfiguration .get ().setProperty (ALLOW_STORE_CREATION_PROPERTY_NAME , "true" );
524+ ArchConfiguration .get ().setProperty (DELETE_EMPTY_RULE_VIOLATION_PROPERTY_NAME , "true" );
525+
526+ ArchRule rule = rule ("some description" ).withoutViolations ().create ();
527+ freeze (rule ).check (importClasses (getClass ()));
528+
529+ assertThat (storeFolder .list ()).containsOnly ("stored.rules" );
530+ String storeContents = String .join ("\n " , readAllLines (storeFolder .toPath ().resolve ("stored.rules" )));
531+ assertThat (storeContents ).doesNotContain (rule .getDescription ());
532+ }
533+
534+ @ Test
535+ public void can_delete_default_ViolationStore_rule_file_for_empty_violations () throws IOException {
536+ // given
537+ File storeFolder = useTemporaryDefaultStorePath ();
538+ ArchConfiguration .get ().setProperty (STORE_PROPERTY_NAME , MyTextFileBasedViolationStore .class .getName ());
539+ ArchConfiguration .get ().setProperty (ALLOW_STORE_CREATION_PROPERTY_NAME , "true" );
540+ ArchConfiguration .get ().setProperty (DELETE_EMPTY_RULE_VIOLATION_PROPERTY_NAME , "true" );
541+
542+ freeze (rule ("some description" ).withViolations ("violation 1" ).create ()).check (importClasses (getClass ()));
543+ assertThat (storeFolder .list ()).containsOnly ("stored.rules" , "some description test" );
544+
545+ // when
546+ ArchRule rule = rule ("some description" ).withoutViolations ().create ();
547+ freeze (rule ).check (importClasses (getClass ()));
548+
549+ // then
550+ assertThat (storeFolder .list ()).containsOnly ("stored.rules" );
551+ String storeContents = String .join ("\n " , readAllLines (storeFolder .toPath ().resolve ("stored.rules" )));
552+ assertThat (storeContents ).doesNotContain (rule .getDescription ());
553+ }
554+
485555 @ Test
486556 public void allows_to_adjust_default_store_file_names_via_delegation () throws IOException {
487557 // GIVEN
0 commit comments