diff --git a/common/src/main/java/me/lucko/luckperms/common/model/Group.java b/common/src/main/java/me/lucko/luckperms/common/model/Group.java index cbcec4ded..c3db40f64 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/Group.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/Group.java @@ -175,7 +175,7 @@ public class Group extends PermissionHolder { public class DisplayNameCache extends Cache> { @Override protected @NonNull Optional supply() { - return calculateDisplayName(getPlugin().getContextManager().getStaticQueryOptions()); + return calculateDisplayName(getQueryOptions()); } } } diff --git a/common/src/main/java/me/lucko/luckperms/common/model/Track.java b/common/src/main/java/me/lucko/luckperms/common/model/Track.java index 0eff019b7..fd2d0ac91 100644 --- a/common/src/main/java/me/lucko/luckperms/common/model/Track.java +++ b/common/src/main/java/me/lucko/luckperms/common/model/Track.java @@ -250,7 +250,7 @@ public final class Track { } /** - * Clear all of the groups within this track + * Clear all of the groups within this trackx */ public void clearGroups() { List before = ImmutableList.copyOf(this.groups); diff --git a/common/src/test/java/me/lucko/luckperms/common/graph/TraversalAlgorithmTest.java b/common/src/test/java/me/lucko/luckperms/common/graph/TraversalAlgorithmTest.java new file mode 100644 index 000000000..fe8b5c146 --- /dev/null +++ b/common/src/test/java/me/lucko/luckperms/common/graph/TraversalAlgorithmTest.java @@ -0,0 +1,87 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.common.graph; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class TraversalAlgorithmTest { + + private static final Node ROOT = new Node("root", + new Node("a", + new Node("a1"), + new Node("a2") + ), + new Node("b", + new Node("b1"), + new Node("b2") + ) + ); + + private static final Graph GRAPH = Node::children; + + @ParameterizedTest + @CsvSource({ + "BREADTH_FIRST, 'root, a, b, a1, a2, b1, b2'", + "DEPTH_FIRST_PRE_ORDER, 'root, a, a1, a2, b, b1, b2'", + "DEPTH_FIRST_POST_ORDER, 'a1, a2, a, b1, b2, b, root'" + }) + public void testTraversal(TraversalAlgorithm alg, String expected) { + Iterable result = GRAPH.traverse(alg, ROOT); + String resultString = StreamSupport.stream(result.spliterator(), false) + .map(n -> n.name) + .collect(Collectors.joining(", ")); + + assertEquals(expected, resultString); + } + + static class Node { + private final String name; + private final List children; + + public Node(String name, Node... children) { + this.name = name; + this.children = Arrays.asList(children); + } + + public List children() { + return this.children; + } + + @Override + public String toString() { + return this.name + "(" + this.children + ")"; + } + } + +} diff --git a/common/src/test/java/me/lucko/luckperms/common/inheritance/InheritanceComparatorTest.java b/common/src/test/java/me/lucko/luckperms/common/inheritance/InheritanceComparatorTest.java new file mode 100644 index 000000000..54ecaaaf8 --- /dev/null +++ b/common/src/test/java/me/lucko/luckperms/common/inheritance/InheritanceComparatorTest.java @@ -0,0 +1,113 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.common.inheritance; + +import me.lucko.luckperms.common.model.Group; +import me.lucko.luckperms.common.model.HolderType; +import me.lucko.luckperms.common.model.PermissionHolder; +import me.lucko.luckperms.common.model.PrimaryGroupHolder; +import me.lucko.luckperms.common.model.User; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.Comparator; +import java.util.List; +import java.util.OptionalInt; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + +public class InheritanceComparatorTest { + + @Test + public void testUserAlwaysFirst() { + User user = makeUser("root", "admin"); + List holders = List.of( + makeGroup("admin", 0), + makeGroup("moderator", 0), + user + ); + + Comparator comparator = InheritanceComparator.getFor(user); + + List results = holders.stream().sorted(comparator).map(PermissionHolder::getPlainDisplayName).collect(Collectors.toList()); + assertEquals(List.of("root", "admin", "moderator"), results); + } + + @Test + public void testPrimaryGroupOrdering() { + User user = makeUser("root", "admin"); + List holders = List.of( + makeGroup("vip", 0), + makeGroup("admin", 0), + makeGroup("moderator", 0) + ); + + Comparator comparator = InheritanceComparator.getFor(user); + + List results = holders.stream().sorted(comparator).map(PermissionHolder::getPlainDisplayName).collect(Collectors.toList()); + assertEquals(List.of("admin", "vip", "moderator"), results); + } + + @Test + public void testWeightOrdering() { + User user = makeUser("root", "vip"); + List holders = List.of( + makeGroup("vip", 3), + makeGroup("admin", 10), + makeGroup("moderator", 5) + ); + + Comparator comparator = InheritanceComparator.getFor(user); + + List results = holders.stream().sorted(comparator).map(PermissionHolder::getPlainDisplayName).collect(Collectors.toList()); + assertEquals(List.of("admin", "moderator", "vip"), results); + } + + private static Group makeGroup(String name, int weight) { + Group group = Mockito.mock(Group.class); + when(group.getType()).thenReturn(HolderType.GROUP); + when(group.getName()).thenReturn(name); + when(group.getPlainDisplayName()).thenReturn(name); + when(group.getWeight()).thenReturn(OptionalInt.of(weight)); + return group; + } + + private static User makeUser(String name, String primaryGroup) { + User user = Mockito.mock(User.class); + when(user.getType()).thenReturn(HolderType.USER); + when(user.getPlainDisplayName()).thenReturn(name); + + PrimaryGroupHolder primaryGroupHolder = new PrimaryGroupHolder.Stored(user); + if (primaryGroup != null) { + primaryGroupHolder.setStoredValue(primaryGroup); + } + + when(user.getPrimaryGroup()).thenReturn(primaryGroupHolder); + return user; + } +} diff --git a/common/src/test/java/me/lucko/luckperms/common/model/GroupTest.java b/common/src/test/java/me/lucko/luckperms/common/model/GroupTest.java new file mode 100644 index 000000000..602b37089 --- /dev/null +++ b/common/src/test/java/me/lucko/luckperms/common/model/GroupTest.java @@ -0,0 +1,136 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.common.model; + +import me.lucko.luckperms.common.config.ConfigKeys; +import me.lucko.luckperms.common.config.LuckPermsConfiguration; +import me.lucko.luckperms.common.context.manager.ContextManager; +import me.lucko.luckperms.common.event.EventDispatcher; +import me.lucko.luckperms.common.node.types.DisplayName; +import me.lucko.luckperms.common.node.types.Weight; +import me.lucko.luckperms.common.plugin.LuckPermsPlugin; +import me.lucko.luckperms.common.query.QueryOptionsImpl; +import net.luckperms.api.context.ContextSatisfyMode; +import net.luckperms.api.model.data.DataType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Map; +import java.util.Optional; +import java.util.OptionalInt; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class GroupTest { + + @Mock private LuckPermsPlugin plugin; + @Mock private LuckPermsConfiguration configuration; + @Mock private ContextManager contextManager; + + @BeforeEach + public void setupMocks() { + lenient().when(this.plugin.getEventDispatcher()).thenReturn(mock(EventDispatcher.class)); + lenient().when(this.plugin.getConfiguration()).thenReturn(this.configuration); + + //noinspection unchecked,rawtypes + lenient().when(this.plugin.getContextManager()).thenReturn((ContextManager) this.contextManager); + } + + @Test + public void testGetWeightEmpty() { + when(this.configuration.get(ConfigKeys.GROUP_WEIGHTS)).thenReturn(Map.of()); + + OptionalInt res = new Group("test", this.plugin).getWeight(); + assertTrue(res.isEmpty()); + } + + @Test + public void testGetWeightFromConfiguration() { + when(this.configuration.get(ConfigKeys.GROUP_WEIGHTS)).thenReturn(Map.of("test", 10)); + + OptionalInt res = new Group("test", this.plugin).getWeight(); + assertTrue(res.isPresent()); + assertEquals(10, res.getAsInt()); + } + + @Test + public void testGetWeightFromNode() { + when(this.configuration.get(ConfigKeys.CONTEXT_SATISFY_MODE)).thenReturn(ContextSatisfyMode.AT_LEAST_ONE_VALUE_PER_KEY); + + Group group = new Group("test", this.plugin); + group.setNode(DataType.NORMAL, Weight.builder(3).build(), false); + group.setNode(DataType.NORMAL, Weight.builder(5).build(), false); + + OptionalInt res = group.getWeight(); + assertTrue(res.isPresent()); + assertEquals(5, res.getAsInt()); + + group.setNode(DataType.NORMAL, Weight.builder(100).build(), false); + + res = group.getWeight(); + assertTrue(res.isPresent()); + assertEquals(100, res.getAsInt()); + } + + @Test + public void testGetDisplayNameEmpty() { + when(this.contextManager.getStaticQueryOptions()).thenReturn(QueryOptionsImpl.DEFAULT_CONTEXTUAL); + when(this.configuration.get(ConfigKeys.GROUP_NAME_REWRITES)).thenReturn(Map.of()); + + Optional displayName = new Group("test", this.plugin).getDisplayName(); + assertTrue(displayName.isEmpty()); + } + + @Test + public void testGetDisplayNameFromConfiguration() { + when(this.contextManager.getStaticQueryOptions()).thenReturn(QueryOptionsImpl.DEFAULT_CONTEXTUAL); + when(this.configuration.get(ConfigKeys.GROUP_NAME_REWRITES)).thenReturn(Map.of("test", "Test")); + + Optional displayName = new Group("test", this.plugin).getDisplayName(); + assertTrue(displayName.isPresent()); + assertEquals("Test", displayName.get()); + } + + @Test + public void testGetDisplayNameFromNode() { + when(this.contextManager.getStaticQueryOptions()).thenReturn(QueryOptionsImpl.DEFAULT_CONTEXTUAL); + + Group group = new Group("test", this.plugin); + group.setNode(DataType.NORMAL, DisplayName.builder("TEST").build(), false); + + Optional displayName = group.getDisplayName(); + assertTrue(displayName.isPresent()); + assertEquals("TEST", displayName.get()); + } +} diff --git a/common/src/test/java/me/lucko/luckperms/common/model/PrimaryGroupHolderTest.java b/common/src/test/java/me/lucko/luckperms/common/model/PrimaryGroupHolderTest.java new file mode 100644 index 000000000..f17df31b4 --- /dev/null +++ b/common/src/test/java/me/lucko/luckperms/common/model/PrimaryGroupHolderTest.java @@ -0,0 +1,133 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.common.model; + +import me.lucko.luckperms.common.config.ConfigKeys; +import me.lucko.luckperms.common.config.LuckPermsConfiguration; +import me.lucko.luckperms.common.event.EventDispatcher; +import me.lucko.luckperms.common.graph.TraversalAlgorithm; +import me.lucko.luckperms.common.inheritance.InheritanceGraphFactory; +import me.lucko.luckperms.common.model.manager.group.GroupManager; +import me.lucko.luckperms.common.model.manager.group.StandardGroupManager; +import me.lucko.luckperms.common.node.types.Inheritance; +import me.lucko.luckperms.common.node.types.Weight; +import me.lucko.luckperms.common.plugin.LuckPermsPlugin; +import me.lucko.luckperms.common.query.QueryOptionsImpl; +import net.luckperms.api.context.ContextSatisfyMode; +import net.luckperms.api.model.data.DataType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class PrimaryGroupHolderTest { + + @Mock private LuckPermsPlugin plugin; + @Mock private LuckPermsConfiguration configuration; + + private StandardGroupManager groupManager; + + @BeforeEach + public void setupMocks() { + this.groupManager = new StandardGroupManager(this.plugin); + + //noinspection unchecked,rawtypes + lenient().when(this.plugin.getGroupManager()).thenReturn((GroupManager) this.groupManager); + lenient().when(this.plugin.getInheritanceGraphFactory()).thenReturn(new InheritanceGraphFactory(this.plugin)); + lenient().when(this.plugin.getConfiguration()).thenReturn(this.configuration); + lenient().when(this.plugin.getEventDispatcher()).thenReturn(mock(EventDispatcher.class)); + lenient().when(this.configuration.get(ConfigKeys.CONTEXT_SATISFY_MODE)).thenReturn(ContextSatisfyMode.AT_LEAST_ONE_VALUE_PER_KEY); + lenient().when(this.configuration.get(ConfigKeys.GROUP_WEIGHTS)).thenReturn(Collections.emptyMap()); + lenient().when(this.configuration.get(ConfigKeys.PRIMARY_GROUP_CALCULATION)).thenReturn(u -> null); + lenient().when(this.configuration.get(ConfigKeys.INHERITANCE_TRAVERSAL_ALGORITHM)).thenReturn(TraversalAlgorithm.BREADTH_FIRST); + } + + @Test + public void testStored() { + User user = new User(UUID.randomUUID(), this.plugin); + + // all holders inherit from stored, and should behave the same in the absence of any nodes + List holders = List.of( + new PrimaryGroupHolder.Stored(user), + new PrimaryGroupHolder.AllParentsByWeight(user), + new PrimaryGroupHolder.ParentsByWeight(user) + ); + + for (PrimaryGroupHolder holder : holders) { + // empty + assertEquals(Optional.empty(), holder.getStoredValue()); + assertNull(holder.calculateValue(QueryOptionsImpl.DEFAULT_CONTEXTUAL)); + + // set value + holder.setStoredValue("test"); + assertEquals(Optional.of("test"), holder.getStoredValue()); + assertEquals("test", holder.calculateValue(QueryOptionsImpl.DEFAULT_CONTEXTUAL)); + } + } + + @Test + public void testParentsByWeight() { + User user = new User(UUID.randomUUID(), this.plugin); + + Group special = createGroup("special", 100, null); // parent of mod, but not inherited directly + Group mod = createGroup("mod", 5, special); + Group admin = createGroup("admin", 10, mod); + + user.setNode(DataType.NORMAL, Inheritance.builder("mod").build(), false); + user.setNode(DataType.NORMAL, Inheritance.builder("admin").build(), false); + + PrimaryGroupHolder holder = new PrimaryGroupHolder.AllParentsByWeight(user); + assertEquals("special", holder.calculateValue(QueryOptionsImpl.DEFAULT_CONTEXTUAL)); + + holder = new PrimaryGroupHolder.ParentsByWeight(user); + assertEquals("admin", holder.calculateValue(QueryOptionsImpl.DEFAULT_CONTEXTUAL)); + } + + private Group createGroup(String name, int weight, Group parent) { + Group group = this.groupManager.getOrMake(name); + if (parent != null) { + group.normalData().add(Inheritance.builder().group(parent.getName()).build()); + } + group.normalData().add(Weight.builder().weight(weight).build()); + return group; + } + +} diff --git a/common/src/test/java/me/lucko/luckperms/common/model/TrackTest.java b/common/src/test/java/me/lucko/luckperms/common/model/TrackTest.java new file mode 100644 index 000000000..fc155521c --- /dev/null +++ b/common/src/test/java/me/lucko/luckperms/common/model/TrackTest.java @@ -0,0 +1,123 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.common.model; + +import me.lucko.luckperms.common.config.LuckPermsConfiguration; +import me.lucko.luckperms.common.event.EventDispatcher; +import me.lucko.luckperms.common.inheritance.InheritanceGraphFactory; +import me.lucko.luckperms.common.model.manager.group.GroupManager; +import me.lucko.luckperms.common.model.manager.group.StandardGroupManager; +import me.lucko.luckperms.common.plugin.LuckPermsPlugin; +import net.luckperms.api.model.data.DataMutateResult; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; + +@ExtendWith(MockitoExtension.class) +public class TrackTest { + + @Mock private LuckPermsPlugin plugin; + @Mock private LuckPermsConfiguration configuration; + + private StandardGroupManager groupManager; + + @BeforeEach + public void setupMocks() { + this.groupManager = new StandardGroupManager(this.plugin); + + //noinspection unchecked,rawtypes + lenient().when(this.plugin.getGroupManager()).thenReturn((GroupManager) this.groupManager); + lenient().when(this.plugin.getInheritanceGraphFactory()).thenReturn(new InheritanceGraphFactory(this.plugin)); + lenient().when(this.plugin.getConfiguration()).thenReturn(this.configuration); + lenient().when(this.plugin.getEventDispatcher()).thenReturn(mock(EventDispatcher.class)); + } + + @Test + public void testGetRelative() { + Track track = new Track("test", this.plugin); + + Group a = this.groupManager.getOrMake("a"); + Group b = this.groupManager.getOrMake("b"); + Group c = this.groupManager.getOrMake("c"); + + track.setGroups(List.of("a", "b", "c")); + assertEquals(List.of("a", "b", "c"), track.getGroups()); + + // next + assertEquals("b", track.getNext(a)); + assertEquals("c", track.getNext(b)); + assertNull(track.getNext(c)); + assertThrows(IllegalArgumentException.class, () -> track.getNext("missing")); + + // previous + assertEquals("b", track.getPrevious(c)); + assertEquals("a", track.getPrevious(b)); + assertNull(track.getPrevious(a)); + assertThrows(IllegalArgumentException.class, () -> track.getPrevious("missing")); + } + + @Test + public void testAppendInsertRemove() { + Track track = new Track("test", this.plugin); + + Group a = this.groupManager.getOrMake("a"); + Group b = this.groupManager.getOrMake("b"); + Group c = this.groupManager.getOrMake("c"); + Group d = this.groupManager.getOrMake("d"); + + track.setGroups(List.of("a", "b")); + assertEquals(List.of("a", "b"), track.getGroups()); + + // append + DataMutateResult res = track.appendGroup(a); + assertEquals(DataMutateResult.FAIL_ALREADY_HAS, res); + + res = track.appendGroup(c); + assertEquals(DataMutateResult.SUCCESS, res); + assertEquals(List.of("a", "b", "c"), track.getGroups()); + + // insert + res = track.insertGroup(d, 1); + assertEquals(DataMutateResult.SUCCESS, res); + assertEquals(List.of("a", "d", "b", "c"), track.getGroups()); + + // remove + res = track.removeGroup(b); + assertEquals(DataMutateResult.SUCCESS, res); + assertEquals(List.of("a", "d", "c"), track.getGroups()); + } + +} diff --git a/common/src/test/java/me/lucko/luckperms/common/model/UserTest.java b/common/src/test/java/me/lucko/luckperms/common/model/UserTest.java new file mode 100644 index 000000000..e3da31ec5 --- /dev/null +++ b/common/src/test/java/me/lucko/luckperms/common/model/UserTest.java @@ -0,0 +1,112 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.common.model; + +import me.lucko.luckperms.common.config.ConfigKeys; +import me.lucko.luckperms.common.config.LuckPermsConfiguration; +import me.lucko.luckperms.common.event.EventDispatcher; +import me.lucko.luckperms.common.plugin.LuckPermsPlugin; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Optional; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; + +@ExtendWith(MockitoExtension.class) +public class UserTest { + + @Mock private LuckPermsPlugin plugin; + @Mock private LuckPermsConfiguration configuration; + + @BeforeEach + public void setupMocks() { + lenient().when(this.plugin.getEventDispatcher()).thenReturn(mock(EventDispatcher.class)); + lenient().when(this.plugin.getConfiguration()).thenReturn(this.configuration); + lenient().when(this.configuration.get(ConfigKeys.PRIMARY_GROUP_CALCULATION)).thenReturn(u -> null); + } + + @Test + public void testGetDisplayName() { + UUID uniqueId = UUID.randomUUID(); + User user = new User(uniqueId, this.plugin); + + // no username set + assertEquals(uniqueId.toString(), user.getPlainDisplayName()); + + // username set + user.setUsername("Luck", true); + assertEquals("Luck", user.getPlainDisplayName()); + } + + @Test + public void testSetUsername() { + User user = new User(UUID.randomUUID(), this.plugin); + + // fail, over 16 chars + boolean res = user.setUsername("123456789123456789", false); + assertFalse(res); + assertEquals(Optional.empty(), user.getUsername()); + + // succeed - none set already + res = user.setUsername("luck", true); + assertTrue(res); + assertEquals(Optional.of("luck"), user.getUsername()); + + // fail - weak=true and username set already + res = user.setUsername("example", true); + assertFalse(res); + assertEquals(Optional.of("luck"), user.getUsername()); + + // succeed - weak=true and only change in case + res = user.setUsername("Luck", true); + assertFalse(res); + assertEquals(Optional.of("Luck"), user.getUsername()); + + // succeed - change in case + res = user.setUsername("LUCK", false); + assertFalse(res); + assertEquals(Optional.of("LUCK"), user.getUsername()); + + // succeed - change in value + res = user.setUsername("example", false); + assertTrue(res); + assertEquals(Optional.of("example"), user.getUsername()); + + // succeed - set to null + res = user.setUsername("", false); + assertTrue(res); + assertEquals(Optional.empty(), user.getUsername()); + } +}