package com.tngtech.archunit.lang.conditions;
import java.util.Collection;
import com.google.common.base.Joiner;
import com.tngtech.archunit.core.domain.JavaFieldAccess;
import com.tngtech.archunit.core.domain.JavaFieldAccess.AccessType;
import com.tngtech.archunit.lang.ConditionEvent;
import com.tngtech.archunit.lang.ConditionEvents;
import com.tngtech.archunit.lang.conditions.FieldAccessCondition.FieldGetAccessCondition;
import com.tngtech.archunit.lang.conditions.FieldAccessCondition.FieldSetAccessCondition;
import org.junit.Test;
import static com.tngtech.archunit.core.domain.JavaFieldAccess.AccessType.GET;
import static com.tngtech.archunit.core.domain.JavaFieldAccess.AccessType.SET;
import static com.tngtech.archunit.core.domain.JavaFieldAccess.Predicates.target;
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.name;
import static com.tngtech.archunit.lang.conditions.testobjects.TestObjects.CALLER_CLASS;
import static com.tngtech.archunit.lang.conditions.testobjects.TestObjects.TARGET_CLASS;
import static org.assertj.core.api.Assertions.assertThat;
public class FieldAccessConditionTest {
@Test
public void condition_satisfied_on_get_field() {
JavaFieldAccess getAccess = accessFromCallerToTargetWithType(GET);
FieldAccessCondition getFieldCondition = new FieldGetAccessCondition(
target(name(getAccess.getTarget().getName())));
ConditionEvents events = new ConditionEvents();
getFieldCondition.check(getAccess, events);
boolean satisfied = !events.containViolation();
assertThat(satisfied).isTrue();
assertReadMessage(getAccess, messageOf(events.getAllowed()));
assertThat(events.getViolating()).isEmpty();
}
@Test
public void condition_on_get_field_not_satisfied_when_set_field() {
JavaFieldAccess setAccess = accessFromCallerToTargetWithType(SET);
FieldAccessCondition getFieldCondition = new FieldGetAccessCondition(
target(name(setAccess.getTarget().getName())));
ConditionEvents events = new ConditionEvents();
getFieldCondition.check(setAccess, events);
boolean satisfied = !events.containViolation();
assertThat(satisfied).isFalse();
assertThat(events.getAllowed()).isEmpty();
assertReadMessage(setAccess, messageOf(events.getViolating()));
}
@Test
public void condition_satisfied_on_set_field() {
JavaFieldAccess setAccess = accessFromCallerToTargetWithType(SET);
FieldAccessCondition setFieldCondition = new FieldSetAccessCondition(
target(name(setAccess.getTarget().getName())));
ConditionEvents events = new ConditionEvents();
setFieldCondition.check(setAccess, events);
boolean satisfied = !events.containViolation();
assertThat(satisfied).isTrue();
assertWriteMessage(setAccess, messageOf(events.getAllowed()));
assertThat(events.getViolating()).isEmpty();
}
@Test
public void condition_satisfied_on_access_field() {
JavaFieldAccess getAccess = accessFromCallerToTargetWithType(GET);
FieldAccessCondition getFieldCondition = new FieldAccessCondition(
target(name(getAccess.getTarget().getName())));
ConditionEvents events = new ConditionEvents();
getFieldCondition.check(getAccess, events);
boolean satisfied = !events.containViolation();
assertThat(satisfied).isTrue();
assertAccessMessage(getAccess, messageOf(events.getAllowed()));
assertThat(events.getViolating()).isEmpty();
}
private String messageOf(Collection<ConditionEvent> events) {
return Joiner.on(" ").join(events);
}
private void assertAccessMessage(JavaFieldAccess getAccess, String description) {
assertDescription(getAccess, "accesses", description);
}
private void assertReadMessage(JavaFieldAccess getAccess, String description) {
assertDescription(getAccess, "gets", description);
}
private void assertWriteMessage(JavaFieldAccess setAccess, String description) {
assertDescription(setAccess, "sets", description);
}
private void assertDescription(JavaFieldAccess access, String accessText, String description) {
assertThat(description)
.contains(accessText)
.contains(access.getOrigin().getFullName())
.contains(access.getTarget().getFullName())
.contains("" + access.getLineNumber());
}
private static JavaFieldAccess accessFromCallerToTargetWithType(AccessType type) {
for (JavaFieldAccess access : CALLER_CLASS.getFieldAccessesFromSelf()) {
if (access.getTarget().getOwner().equals(TARGET_CLASS) && access.getAccessType() == type) {
return access;
}
}
throw new RuntimeException(CALLER_CLASS + " has no field access with type " + type);
}
}