From bf1f0dfd683bb3d2c6c66f31e23c60b6c93db178 Mon Sep 17 00:00:00 2001 From: Nicolas Payette Date: Wed, 5 Feb 2025 17:29:23 +0000 Subject: [PATCH] add predicate operators for regulations --- .../agents/regulations/PermittedIf.java | 36 +++++ .../regulations/PermittedIfFactory.java | 44 ++++++ .../agents/regulations/Regulations.java | 6 + .../predicates/operators/AllOf.java | 41 ++++++ .../predicates/operators/AllOfFactory.java | 53 ++++++++ .../predicates/operators/AnyOf.java | 41 ++++++ .../predicates/operators/AnyOfFactory.java | 53 ++++++++ .../regulations/predicates/operators/Not.java | 40 ++++++ .../predicates/operators/NotFactory.java | 45 +++++++ .../operators/AllOfFactoryTest.java | 106 +++++++++++++++ .../predicates/operators/AllOfTest.java | 101 ++++++++++++++ .../operators/AnyOfFactoryTest.java | 101 ++++++++++++++ .../predicates/operators/AnyOfTest.java | 125 ++++++++++++++++++ .../predicates/operators/NotFactoryTest.java | 80 +++++++++++ .../predicates/operators/NotTest.java | 68 ++++++++++ 15 files changed, 940 insertions(+) create mode 100644 agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/PermittedIf.java create mode 100644 agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/PermittedIfFactory.java create mode 100644 agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AllOf.java create mode 100644 agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AllOfFactory.java create mode 100644 agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AnyOf.java create mode 100644 agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AnyOfFactory.java create mode 100644 agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/Not.java create mode 100644 agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/NotFactory.java create mode 100644 agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AllOfFactoryTest.java create mode 100644 agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AllOfTest.java create mode 100644 agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AnyOfFactoryTest.java create mode 100644 agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AnyOfTest.java create mode 100644 agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/NotFactoryTest.java create mode 100644 agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/NotTest.java diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/PermittedIf.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/PermittedIf.java new file mode 100644 index 000000000..4a54eb017 --- /dev/null +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/PermittedIf.java @@ -0,0 +1,36 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2025 CoHESyS Lab cohesys.lab@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package uk.ac.ox.poseidon.agents.regulations; + +import lombok.RequiredArgsConstructor; +import uk.ac.ox.poseidon.agents.behaviours.Action; + +import java.util.function.Predicate; + +@RequiredArgsConstructor +public class PermittedIf implements Regulations { + + private final Predicate actionPredicate; + + @Override + public boolean isPermitted(final Action action) { + return actionPredicate.test(action); + } +} diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/PermittedIfFactory.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/PermittedIfFactory.java new file mode 100644 index 000000000..f35f9befd --- /dev/null +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/PermittedIfFactory.java @@ -0,0 +1,44 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2025 CoHESyS Lab cohesys.lab@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package uk.ac.ox.poseidon.agents.regulations; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import uk.ac.ox.poseidon.agents.behaviours.Action; +import uk.ac.ox.poseidon.core.GlobalScopeFactory; +import uk.ac.ox.poseidon.core.Simulation; + +import java.util.function.Predicate; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class PermittedIfFactory extends GlobalScopeFactory { + + private GlobalScopeFactory> actionPredicate; + + @Override + protected PermittedIf newInstance(final Simulation simulation) { + return new PermittedIf(actionPredicate.get(simulation)); + } +} diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/Regulations.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/Regulations.java index 8e76034ff..a7c2f0acb 100644 --- a/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/Regulations.java +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/Regulations.java @@ -23,5 +23,11 @@ @FunctionalInterface public interface Regulations { + boolean isPermitted(Action action); + + default boolean isForbidden(final Action action) { + return !isPermitted(action); + } + } diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AllOf.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AllOf.java new file mode 100644 index 000000000..14abe1f4f --- /dev/null +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AllOf.java @@ -0,0 +1,41 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2025 CoHESyS Lab cohesys.lab@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package uk.ac.ox.poseidon.agents.regulations.predicates.operators; + +import com.google.common.collect.ImmutableList; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import uk.ac.ox.poseidon.agents.behaviours.Action; + +import java.util.function.Predicate; + +@Getter +@RequiredArgsConstructor +public class AllOf implements Predicate { + + @NonNull + private final ImmutableList> predicates; + + @Override + public boolean test(final Action action) { + return predicates.stream().allMatch(predicate -> predicate.test(action)); + } +} diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AllOfFactory.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AllOfFactory.java new file mode 100644 index 000000000..c54118842 --- /dev/null +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AllOfFactory.java @@ -0,0 +1,53 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2025 CoHESyS Lab cohesys.lab@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package uk.ac.ox.poseidon.agents.regulations.predicates.operators; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import uk.ac.ox.poseidon.agents.behaviours.Action; +import uk.ac.ox.poseidon.core.Factory; +import uk.ac.ox.poseidon.core.GlobalScopeFactory; +import uk.ac.ox.poseidon.core.Simulation; + +import java.util.List; +import java.util.function.Predicate; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class AllOfFactory extends GlobalScopeFactory { + + List>> predicates; + + @Override + protected AllOf newInstance(final Simulation simulation) { + return new AllOf( + predicates + .stream() + .map(p -> p.get(simulation)) + .collect(toImmutableList()) + ); + } +} diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AnyOf.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AnyOf.java new file mode 100644 index 000000000..5ebe1f153 --- /dev/null +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AnyOf.java @@ -0,0 +1,41 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2025 CoHESyS Lab cohesys.lab@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package uk.ac.ox.poseidon.agents.regulations.predicates.operators; + +import com.google.common.collect.ImmutableList; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import uk.ac.ox.poseidon.agents.behaviours.Action; + +import java.util.function.Predicate; + +@Getter +@RequiredArgsConstructor +public class AnyOf implements Predicate { + + @NonNull + private final ImmutableList> predicates; + + @Override + public boolean test(final Action action) { + return predicates.stream().anyMatch(predicate -> predicate.test(action)); + } +} diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AnyOfFactory.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AnyOfFactory.java new file mode 100644 index 000000000..836306c54 --- /dev/null +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AnyOfFactory.java @@ -0,0 +1,53 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2025 CoHESyS Lab cohesys.lab@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package uk.ac.ox.poseidon.agents.regulations.predicates.operators; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import uk.ac.ox.poseidon.agents.behaviours.Action; +import uk.ac.ox.poseidon.core.Factory; +import uk.ac.ox.poseidon.core.GlobalScopeFactory; +import uk.ac.ox.poseidon.core.Simulation; + +import java.util.List; +import java.util.function.Predicate; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class AnyOfFactory extends GlobalScopeFactory { + + List>> predicates; + + @Override + protected AnyOf newInstance(final Simulation simulation) { + return new AnyOf( + predicates + .stream() + .map(p -> p.get(simulation)) + .collect(toImmutableList()) + ); + } +} diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/Not.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/Not.java new file mode 100644 index 000000000..859fcdd7f --- /dev/null +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/Not.java @@ -0,0 +1,40 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2025 CoHESyS Lab cohesys.lab@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package uk.ac.ox.poseidon.agents.regulations.predicates.operators; + +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import uk.ac.ox.poseidon.agents.behaviours.Action; + +import java.util.function.Predicate; + +@Getter +@RequiredArgsConstructor +public class Not implements Predicate { + + @NonNull + private final Predicate predicate; + + @Override + public boolean test(final Action action) { + return !predicate.test(action); + } +} diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/NotFactory.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/NotFactory.java new file mode 100644 index 000000000..4bd060c96 --- /dev/null +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/NotFactory.java @@ -0,0 +1,45 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2025 CoHESyS Lab cohesys.lab@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package uk.ac.ox.poseidon.agents.regulations.predicates.operators; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import uk.ac.ox.poseidon.agents.behaviours.Action; +import uk.ac.ox.poseidon.core.Factory; +import uk.ac.ox.poseidon.core.GlobalScopeFactory; +import uk.ac.ox.poseidon.core.Simulation; + +import java.util.function.Predicate; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class NotFactory extends GlobalScopeFactory { + + private Factory> predicate; + + @Override + protected Not newInstance(final Simulation simulation) { + return new Not(predicate.get(simulation)); + } +} diff --git a/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AllOfFactoryTest.java b/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AllOfFactoryTest.java new file mode 100644 index 000000000..21f5d5a88 --- /dev/null +++ b/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AllOfFactoryTest.java @@ -0,0 +1,106 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2025 CoHESyS Lab cohesys.lab@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package uk.ac.ox.poseidon.agents.regulations.predicates.operators; + +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import uk.ac.ox.poseidon.agents.behaviours.Action; +import uk.ac.ox.poseidon.core.Factory; +import uk.ac.ox.poseidon.core.Simulation; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class AllOfFactoryTest { + + /** + * Test class for AllOfFactory. AllOfFactory is responsible for creating instances of AllOf. The + * method `newInstance` initializes an AllOf object with a collection of predicates by + * retrieving them through factories in the context of a provided simulation. + */ + + @Test + void testNewInstanceWithEmptyPredicates() { + // Arrange + final List>> predicateFactories = new ArrayList<>(); + final AllOfFactory allOfFactory = new AllOfFactory(predicateFactories); + final Simulation mockSimulation = mock(Simulation.class); + + // Act + final AllOf result = allOfFactory.newInstance(mockSimulation); + + // Assert + assertEquals(0, result.getPredicates().size()); + } + + @Test + void testNewInstanceWithSinglePredicate() { + // Arrange + final Predicate mockPredicate = mock(Predicate.class); + final Factory> mockFactory = mock(Factory.class); + when(mockFactory.get(Mockito.any(Simulation.class))).thenReturn(mockPredicate); + + final List>> predicateFactories = List.of(mockFactory); + final AllOfFactory allOfFactory = new AllOfFactory(predicateFactories); + final Simulation mockSimulation = mock(Simulation.class); + + // Act + final AllOf result = allOfFactory.newInstance(mockSimulation); + + // Assert + assertEquals(1, result.getPredicates().size()); + assertEquals(mockPredicate, result.getPredicates().iterator().next()); + } + + @Test + void testNewInstanceWithMultiplePredicates() { + // Arrange + final Predicate mockPredicate1 = mock(Predicate.class); + final Predicate mockPredicate2 = mock(Predicate.class); + + final Factory> mockFactory1 = mock(Factory.class); + final Factory> mockFactory2 = mock(Factory.class); + + when(mockFactory1.get(Mockito.any(Simulation.class))).thenReturn(mockPredicate1); + when(mockFactory2.get(Mockito.any(Simulation.class))).thenReturn(mockPredicate2); + + final List>> predicateFactories = List.of( + mockFactory1, + mockFactory2 + ); + final AllOfFactory allOfFactory = new AllOfFactory(predicateFactories); + final Simulation mockSimulation = mock(Simulation.class); + + // Act + final AllOf result = allOfFactory.newInstance(mockSimulation); + + // Assert + assertEquals(2, result.getPredicates().size()); + assertEquals( + List.of(mockPredicate1, mockPredicate2), + new ArrayList<>(result.getPredicates()) + ); + } +} diff --git a/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AllOfTest.java b/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AllOfTest.java new file mode 100644 index 000000000..551003ea2 --- /dev/null +++ b/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AllOfTest.java @@ -0,0 +1,101 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2025 CoHESyS Lab cohesys.lab@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package uk.ac.ox.poseidon.agents.regulations.predicates.operators; + +import com.google.common.collect.ImmutableList; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import uk.ac.ox.poseidon.agents.behaviours.Action; + +import java.util.function.Predicate; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class AllOfTest { + + /** + * Tests the {@link AllOf#test(Action)} method which checks if all predicates in the collection + * return true for the given action. + */ + + @Test + void testAllPredicatesReturnTrue() { + final Action action = Mockito.mock(Action.class); + + final Predicate predicate1 = Mockito.mock(Predicate.class); + final Predicate predicate2 = Mockito.mock(Predicate.class); + final Predicate predicate3 = Mockito.mock(Predicate.class); + + Mockito.when(predicate1.test(action)).thenReturn(true); + Mockito.when(predicate2.test(action)).thenReturn(true); + Mockito.when(predicate3.test(action)).thenReturn(true); + + final AllOf allOf = new AllOf(ImmutableList.of(predicate1, predicate2, predicate3)); + assertTrue(allOf.test(action), "Expected all predicates to return true."); + } + + @Test + void testOnePredicateReturnsFalse() { + final Action action = Mockito.mock(Action.class); + + final Predicate predicate1 = Mockito.mock(Predicate.class); + final Predicate predicate2 = Mockito.mock(Predicate.class); + final Predicate predicate3 = Mockito.mock(Predicate.class); + + Mockito.when(predicate1.test(action)).thenReturn(true); + Mockito.when(predicate2.test(action)).thenReturn(false); + Mockito.when(predicate3.test(action)).thenReturn(true); + + final AllOf allOf = new AllOf(ImmutableList.of(predicate1, predicate2, predicate3)); + assertFalse( + allOf.test(action), + "Expected test to return false as one predicate returned false." + ); + } + + @Test + void testAllPredicatesReturnFalse() { + final Action action = Mockito.mock(Action.class); + + final Predicate predicate1 = Mockito.mock(Predicate.class); + final Predicate predicate2 = Mockito.mock(Predicate.class); + + Mockito.when(predicate1.test(action)).thenReturn(false); + Mockito.when(predicate2.test(action)).thenReturn(false); + + final AllOf allOf = new AllOf(ImmutableList.of(predicate1, predicate2)); + assertFalse( + allOf.test(action), + "Expected test to return false as all predicates returned false." + ); + } + + @Test + void testEmptyPredicates() { + final Action action = Mockito.mock(Action.class); + + final AllOf allOf = new AllOf(ImmutableList.of()); + assertTrue( + allOf.test(action), + "Expected test to return true as no predicates are present." + ); + } +} diff --git a/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AnyOfFactoryTest.java b/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AnyOfFactoryTest.java new file mode 100644 index 000000000..23703bc8f --- /dev/null +++ b/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AnyOfFactoryTest.java @@ -0,0 +1,101 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2025 CoHESyS Lab cohesys.lab@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package uk.ac.ox.poseidon.agents.regulations.predicates.operators; + +import org.junit.jupiter.api.Test; +import uk.ac.ox.poseidon.agents.behaviours.Action; +import uk.ac.ox.poseidon.core.Factory; +import uk.ac.ox.poseidon.core.Simulation; + +import java.util.List; +import java.util.function.Predicate; + +import static com.google.common.collect.ImmutableList.toImmutableList; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +class AnyOfFactoryTest { + + /** + * Test class for AnyOfFactory's `newInstance` method. Verifies that the method correctly + * creates an instance of the AnyOf class where predicate factories are resolved with the + * provided simulation and stored properly. + */ + + @Test + void testNewInstance_ValidPredicates() { + // Arrange + final Simulation simulation = mock(Simulation.class); + final Factory> predicateFactory1 = mock(Factory.class); + final Factory> predicateFactory2 = mock(Factory.class); + final Predicate predicate1 = mock(Predicate.class); + final Predicate predicate2 = mock(Predicate.class); + + when(predicateFactory1.get(simulation)).thenReturn(predicate1); + when(predicateFactory2.get(simulation)).thenReturn(predicate2); + + final List>> predicateFactories = List.of( + predicateFactory1, + predicateFactory2 + ); + final AnyOfFactory anyOfFactory = new AnyOfFactory(predicateFactories); + + // Act + final AnyOf anyOf = anyOfFactory.newInstance(simulation); + + // Assert + assertNotNull(anyOf); + verify(predicateFactory1, times(1)).get(simulation); + verify(predicateFactory2, times(1)).get(simulation); + assertEquals( + predicateFactories + .stream() + .map(factory -> factory.get(simulation)) + .collect(toImmutableList()), + anyOf.getPredicates() + ); + + } + + @Test + void testNewInstance_EmptyPredicates() { + // Arrange + final Simulation simulation = mock(Simulation.class); + final AnyOfFactory anyOfFactory = new AnyOfFactory(List.of()); + + // Act + final AnyOf anyOf = anyOfFactory.newInstance(simulation); + + // Assert + assertNotNull(anyOf); + assertEquals(0, anyOf.getPredicates().size()); + } + + @Test + void testNewInstance_NullPredicateFactory() { + // Arrange + final Simulation simulation = mock(Simulation.class); + final Factory> nullFactory = __ -> null; + final AnyOfFactory anyOfFactory = new AnyOfFactory(List.of(nullFactory)); + + // Act & Assert + assertThrows(NullPointerException.class, () -> anyOfFactory.newInstance(simulation)); + } +} diff --git a/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AnyOfTest.java b/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AnyOfTest.java new file mode 100644 index 000000000..f05667574 --- /dev/null +++ b/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/AnyOfTest.java @@ -0,0 +1,125 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2025 CoHESyS Lab cohesys.lab@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package uk.ac.ox.poseidon.agents.regulations.predicates.operators; + +import com.google.common.collect.ImmutableList; +import org.junit.jupiter.api.Test; +import uk.ac.ox.poseidon.agents.behaviours.Action; + +import java.util.function.Predicate; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class AnyOfTest { + + /** + * Tests the {@link AnyOf} class, which holds a collection of predicates and evaluates if any of + * them return true when applied to a given {@link Action}. + */ + + @Test + void test_whenAnyPredicateMatches_shouldReturnTrue() { + // Arrange + final Action action = mock(Action.class); + final Predicate predicate1 = mock(Predicate.class); + final Predicate predicate2 = mock(Predicate.class); + + when(predicate1.test(action)).thenReturn(false); + when(predicate2.test(action)).thenReturn(true); + + final AnyOf anyOf = new AnyOf(ImmutableList.of(predicate1, predicate2)); + + // Act + final boolean result = anyOf.test(action); + + // Assert + assertTrue(result); + } + + @Test + void test_whenNoPredicatesMatch_shouldReturnFalse() { + // Arrange + final Action action = mock(Action.class); + final Predicate predicate1 = mock(Predicate.class); + final Predicate predicate2 = mock(Predicate.class); + + when(predicate1.test(action)).thenReturn(false); + when(predicate2.test(action)).thenReturn(false); + + final AnyOf anyOf = new AnyOf(ImmutableList.of(predicate1, predicate2)); + + // Act + final boolean result = anyOf.test(action); + + // Assert + assertFalse(result); + } + + @Test + void test_whenNoPredicatesProvided_shouldReturnFalse() { + // Arrange + final Action action = mock(Action.class); + + final AnyOf anyOf = new AnyOf(ImmutableList.of()); + + // Act + final boolean result = anyOf.test(action); + + // Assert + assertFalse(result); + } + + @Test + void test_whenSinglePredicateMatches_shouldReturnTrue() { + // Arrange + final Action action = mock(Action.class); + final Predicate predicate = mock(Predicate.class); + + when(predicate.test(action)).thenReturn(true); + + final AnyOf anyOf = new AnyOf(ImmutableList.of(predicate)); + + // Act + final boolean result = anyOf.test(action); + + // Assert + assertTrue(result); + } + + @Test + void test_whenSinglePredicateDoesNotMatch_shouldReturnFalse() { + // Arrange + final Action action = mock(Action.class); + final Predicate predicate = mock(Predicate.class); + + when(predicate.test(action)).thenReturn(false); + + final AnyOf anyOf = new AnyOf(ImmutableList.of(predicate)); + + // Act + final boolean result = anyOf.test(action); + + // Assert + assertFalse(result); + } +} diff --git a/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/NotFactoryTest.java b/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/NotFactoryTest.java new file mode 100644 index 000000000..56877b224 --- /dev/null +++ b/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/NotFactoryTest.java @@ -0,0 +1,80 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2025 CoHESyS Lab cohesys.lab@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package uk.ac.ox.poseidon.agents.regulations.predicates.operators; + +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import uk.ac.ox.poseidon.agents.behaviours.Action; +import uk.ac.ox.poseidon.core.Factory; +import uk.ac.ox.poseidon.core.Simulation; + +import java.util.function.Predicate; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class NotFactoryTest { + + /** + * Tests the `newInstance` method of the NotFactory class. Verifies that the method creates a + * `Not` instance correctly when a valid `Factory` for a `Predicate` is provided and is + * functional. + */ + @Test + void testNewInstanceWithValidPredicateFactory() { + // Arrange + final Factory> mockFactory = mock(Factory.class); + final Predicate mockPredicate = mock(Predicate.class); + final Simulation mockSimulation = mock(Simulation.class); + + when(mockFactory.get(Mockito.any())).thenReturn(mockPredicate); + + final NotFactory notFactory = new NotFactory(mockFactory); + + // Act + final Not result = notFactory.newInstance(mockSimulation); + + // Assert + assertNotNull(result, "The resulting Not instance should not be null."); + } + + /** + * Tests the `newInstance` method to ensure it throws a NullPointerException when the factory + * provides a null predicate. + */ + @Test + void testNewInstanceWithNullPredicateThrowsException() { + // Arrange + final Factory> mockFactory = mock(Factory.class); + final Simulation mockSimulation = mock(Simulation.class); + + when(mockFactory.get(Mockito.any())).thenReturn(null); + + final NotFactory notFactory = new NotFactory(mockFactory); + + // Act & Assert + assertThrows( + NullPointerException.class, () -> notFactory.newInstance(mockSimulation), + "Expected Not to throw NullPointerException when the predicate is null." + ); + } +} diff --git a/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/NotTest.java b/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/NotTest.java new file mode 100644 index 000000000..afa71c13f --- /dev/null +++ b/agents/src/test/java/uk/ac/ox/poseidon/agents/regulations/predicates/operators/NotTest.java @@ -0,0 +1,68 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2025 CoHESyS Lab cohesys.lab@gmail.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package uk.ac.ox.poseidon.agents.regulations.predicates.operators; + +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import uk.ac.ox.poseidon.agents.behaviours.Action; + +import java.util.function.Predicate; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class NotTest { + + @Test + void testWhenInnerPredicateReturnsTrue() { + // Arrange + final Predicate innerPredicate = Mockito.mock(Predicate.class); + Mockito.when(innerPredicate.test(Mockito.any())).thenReturn(true); + final Not notPredicate = new Not(innerPredicate); + final Action mockAction = Mockito.mock(Action.class); + + // Act + final boolean result = notPredicate.test(mockAction); + + // Assert + assertFalse( + result, + "The Not predicate should return false when the inner predicate returns true." + ); + } + + @Test + void testWhenInnerPredicateReturnsFalse() { + // Arrange + final Predicate innerPredicate = Mockito.mock(Predicate.class); + Mockito.when(innerPredicate.test(Mockito.any())).thenReturn(false); + final Not notPredicate = new Not(innerPredicate); + final Action mockAction = Mockito.mock(Action.class); + + // Act + final boolean result = notPredicate.test(mockAction); + + // Assert + assertTrue( + result, + "The Not predicate should return true when the inner predicate returns false." + ); + } +}