mirror of
https://github.com/lucko/LuckPerms.git
synced 2025-08-30 17:49:48 +02:00
Add more unit tests
This commit is contained in:
@@ -48,7 +48,7 @@ public interface DataTypeFilterFunction {
|
||||
|
||||
/**
|
||||
* Creates a {@link DataTypeFilterFunction} that always returns the given
|
||||
* {@code predicate}.
|
||||
* {@code predicate} (commonly one of the values in {@link DataTypeFilter}).
|
||||
*
|
||||
* @param predicate the predicate
|
||||
* @return the data type filter function
|
||||
|
@@ -19,7 +19,7 @@ dependencies {
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.1'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.1'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.9.1'
|
||||
testImplementation "org.testcontainers:junit-jupiter:1.19.8"
|
||||
testImplementation 'org.testcontainers:junit-jupiter:1.20.4'
|
||||
testImplementation 'org.mockito:mockito-core:5.11.0'
|
||||
testImplementation 'org.mockito:mockito-junit-jupiter:5.11.0'
|
||||
testImplementation 'com.h2database:h2:2.1.214'
|
||||
|
@@ -26,8 +26,8 @@
|
||||
package me.lucko.luckperms.common.api.implementation;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import me.lucko.luckperms.common.metastacking.SimpleMetaStackDefinition;
|
||||
import me.lucko.luckperms.common.metastacking.StandardStackElements;
|
||||
import me.lucko.luckperms.common.cacheddata.metastack.SimpleMetaStackDefinition;
|
||||
import me.lucko.luckperms.common.cacheddata.metastack.StandardStackElements;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import net.luckperms.api.metastacking.DuplicateRemovalFunction;
|
||||
import net.luckperms.api.metastacking.MetaStackDefinition;
|
||||
|
@@ -193,7 +193,7 @@ public abstract class AbstractCachedDataManager implements CachedDataManager {
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
this.cache.values().removeIf(value -> ((UsageTracked) value).usedSince(TimeUnit.MINUTES.toMillis(2)));
|
||||
this.cache.values().removeIf(value -> !((UsageTracked) value).usedInTheLast(2, TimeUnit.MINUTES));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -25,14 +25,20 @@
|
||||
|
||||
package me.lucko.luckperms.common.cacheddata;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public abstract class UsageTracked {
|
||||
private long lastUsed = System.currentTimeMillis();
|
||||
|
||||
@VisibleForTesting
|
||||
protected long lastUsed = System.currentTimeMillis();
|
||||
|
||||
public void recordUsage() {
|
||||
this.lastUsed = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public boolean usedSince(long duration) {
|
||||
return this.lastUsed > System.currentTimeMillis() - duration;
|
||||
public boolean usedInTheLast(long duration, TimeUnit unit) {
|
||||
return this.lastUsed > System.currentTimeMillis() - unit.toMillis(duration);
|
||||
}
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.metastacking;
|
||||
package me.lucko.luckperms.common.cacheddata.metastack;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
@@ -23,7 +23,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.metastacking;
|
||||
package me.lucko.luckperms.common.cacheddata.metastack;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.luckperms.api.metastacking.DuplicateRemovalFunction;
|
@@ -23,7 +23,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.metastacking;
|
||||
package me.lucko.luckperms.common.cacheddata.metastack;
|
||||
|
||||
import me.lucko.luckperms.common.model.Track;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
@@ -220,8 +220,11 @@ public final class StandardStackElements {
|
||||
@Override
|
||||
public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode<?, ?> node, @Nullable ChatMetaNode<?, ?> current) {
|
||||
Track track = this.plugin.getTrackManager().getIfLoaded(this.trackName);
|
||||
if (track == null) {
|
||||
return false;
|
||||
}
|
||||
PermissionHolder.Identifier origin = node.metadata(InheritanceOriginMetadata.KEY).getOrigin();
|
||||
return track != null && origin.getType().equals(PermissionHolder.Identifier.GROUP_TYPE) && track.containsGroup(origin.getName());
|
||||
return origin.getType().equals(PermissionHolder.Identifier.GROUP_TYPE) && track.containsGroup(origin.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -250,8 +253,11 @@ public final class StandardStackElements {
|
||||
@Override
|
||||
public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode<?, ?> node, @Nullable ChatMetaNode<?, ?> current) {
|
||||
Track track = this.plugin.getTrackManager().getIfLoaded(this.trackName);
|
||||
if (track == null) {
|
||||
return false;
|
||||
}
|
||||
PermissionHolder.Identifier origin = node.metadata(InheritanceOriginMetadata.KEY).getOrigin();
|
||||
return track != null && !track.containsGroup(origin.getName());
|
||||
return !(origin.getType().equals(PermissionHolder.Identifier.GROUP_TYPE) && track.containsGroup(origin.getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -305,7 +311,7 @@ public final class StandardStackElements {
|
||||
@Override
|
||||
public boolean shouldAccumulate(@NonNull ChatMetaType type, @NonNull ChatMetaNode<?, ?> node, @Nullable ChatMetaNode<?, ?> current) {
|
||||
PermissionHolder.Identifier origin = node.metadata(InheritanceOriginMetadata.KEY).getOrigin();
|
||||
return !this.groupName.equals(origin.getName());
|
||||
return !(origin.getType().equals(PermissionHolder.Identifier.GROUP_TYPE) && this.groupName.equals(origin.getName()));
|
||||
}
|
||||
|
||||
@Override
|
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* 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.cacheddata.result;
|
||||
|
||||
import net.luckperms.api.cacheddata.Result;
|
||||
import net.luckperms.api.node.Node;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public abstract class AbstractResult<T, N extends Node, S extends AbstractResult<T, N, S>> implements Result<T, N> {
|
||||
|
||||
/** The node that caused the result */
|
||||
protected final N node;
|
||||
/** A reference to another result that this one overrides */
|
||||
protected S overriddenResult;
|
||||
|
||||
public AbstractResult(N node, S overriddenResult) {
|
||||
this.node = node;
|
||||
this.overriddenResult = overriddenResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final @Nullable N node() {
|
||||
return this.node;
|
||||
}
|
||||
|
||||
public final @Nullable S overriddenResult() {
|
||||
return this.overriddenResult;
|
||||
}
|
||||
|
||||
public final void setOverriddenResult(S overriddenResult) {
|
||||
this.overriddenResult = overriddenResult;
|
||||
}
|
||||
|
||||
}
|
@@ -25,30 +25,23 @@
|
||||
|
||||
package me.lucko.luckperms.common.cacheddata.result;
|
||||
|
||||
import net.luckperms.api.cacheddata.Result;
|
||||
import net.luckperms.api.node.Node;
|
||||
import net.luckperms.api.node.types.WeightNode;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* Represents the result of an integer meta lookup
|
||||
*
|
||||
* @param <N> the node type
|
||||
*/
|
||||
public final class IntegerResult<N extends Node> implements Result<Integer, N> {
|
||||
public final class IntegerResult<N extends Node> extends AbstractResult<Integer, N, IntegerResult<N>> {
|
||||
|
||||
/** The result */
|
||||
private final int result;
|
||||
/** The node that caused the result */
|
||||
private final N node;
|
||||
/** A reference to another result that this one overrides */
|
||||
private IntegerResult<N> overriddenResult;
|
||||
|
||||
public IntegerResult(int result, N node, IntegerResult<N> overriddenResult) {
|
||||
super(node, overriddenResult);
|
||||
this.result = result;
|
||||
this.node = node;
|
||||
this.overriddenResult = overriddenResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -73,19 +66,6 @@ public final class IntegerResult<N extends Node> implements Result<Integer, N> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable N node() {
|
||||
return this.node;
|
||||
}
|
||||
|
||||
public @Nullable IntegerResult<N> overriddenResult() {
|
||||
return this.overriddenResult;
|
||||
}
|
||||
|
||||
public void setOverriddenResult(IntegerResult<N> overriddenResult) {
|
||||
this.overriddenResult = overriddenResult;
|
||||
}
|
||||
|
||||
public boolean isNull() {
|
||||
return this == NULL_RESULT;
|
||||
}
|
||||
|
@@ -25,7 +25,6 @@
|
||||
|
||||
package me.lucko.luckperms.common.cacheddata.result;
|
||||
|
||||
import net.luckperms.api.cacheddata.Result;
|
||||
import net.luckperms.api.node.Node;
|
||||
import net.luckperms.api.node.types.ChatMetaNode;
|
||||
import net.luckperms.api.node.types.MetaNode;
|
||||
@@ -36,19 +35,14 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
*
|
||||
* @param <N> the node type
|
||||
*/
|
||||
public final class StringResult<N extends Node> implements Result<String, N> {
|
||||
public final class StringResult<N extends Node> extends AbstractResult<String, N, StringResult<N>> {
|
||||
|
||||
/** The result, nullable */
|
||||
private final String result;
|
||||
/** The node that caused the result */
|
||||
private final N node;
|
||||
/** A reference to another result that this one overrides */
|
||||
private StringResult<N> overriddenResult;
|
||||
|
||||
public StringResult(String result, N node, StringResult<N> overriddenResult) {
|
||||
super(node, overriddenResult);
|
||||
this.result = result;
|
||||
this.node = node;
|
||||
this.overriddenResult = overriddenResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -56,19 +50,6 @@ public final class StringResult<N extends Node> implements Result<String, N> {
|
||||
return this.result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable N node() {
|
||||
return this.node;
|
||||
}
|
||||
|
||||
public @Nullable StringResult<N> overriddenResult() {
|
||||
return this.overriddenResult;
|
||||
}
|
||||
|
||||
public void setOverriddenResult(StringResult<N> overriddenResult) {
|
||||
this.overriddenResult = overriddenResult;
|
||||
}
|
||||
|
||||
public StringResult<N> copy() {
|
||||
return new StringResult<>(this.result, this.node, this.overriddenResult);
|
||||
}
|
||||
|
@@ -27,7 +27,6 @@ package me.lucko.luckperms.common.cacheddata.result;
|
||||
|
||||
import me.lucko.luckperms.common.calculator.PermissionCalculator;
|
||||
import me.lucko.luckperms.common.calculator.processor.PermissionProcessor;
|
||||
import net.luckperms.api.cacheddata.Result;
|
||||
import net.luckperms.api.node.Node;
|
||||
import net.luckperms.api.util.Tristate;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
@@ -36,20 +35,16 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
/**
|
||||
* Represents the result of a {@link PermissionCalculator} lookup.
|
||||
*/
|
||||
public final class TristateResult implements Result<Tristate, Node> {
|
||||
public final class TristateResult extends AbstractResult<Tristate, Node, TristateResult> {
|
||||
|
||||
/** The result */
|
||||
private final Tristate result;
|
||||
/** The node that caused the result */
|
||||
private final Node node;
|
||||
/** The permission processor that provided the result */
|
||||
private final Class<? extends PermissionProcessor> processorClass;
|
||||
/** A reference to another result that this one overrides */
|
||||
private TristateResult overriddenResult;
|
||||
|
||||
private TristateResult(Tristate result, Node node, Class<? extends PermissionProcessor> processorClass) {
|
||||
super(node, null);
|
||||
this.result = result;
|
||||
this.node = node;
|
||||
this.processorClass = processorClass;
|
||||
}
|
||||
|
||||
@@ -58,11 +53,6 @@ public final class TristateResult implements Result<Tristate, Node> {
|
||||
return this.result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Node node() {
|
||||
return this.node;
|
||||
}
|
||||
|
||||
public @Nullable Class<? extends PermissionProcessor> processorClass() {
|
||||
return this.processorClass;
|
||||
}
|
||||
@@ -79,14 +69,6 @@ public final class TristateResult implements Result<Tristate, Node> {
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable TristateResult overriddenResult() {
|
||||
return this.overriddenResult;
|
||||
}
|
||||
|
||||
public void setOverriddenResult(TristateResult overriddenResult) {
|
||||
this.overriddenResult = overriddenResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TristateResult(" +
|
||||
|
@@ -31,6 +31,7 @@ import me.lucko.luckperms.common.command.spec.CommandSpec;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
@@ -66,7 +67,7 @@ public abstract class ChildCommand<T> extends Command<T> {
|
||||
.collect(Collectors.toList());
|
||||
|
||||
builder.append(Component.text(" - ", NamedTextColor.DARK_AQUA))
|
||||
.append(Component.join(Component.space(), argUsages))
|
||||
.append(Component.join(JoinConfiguration.separator(Component.space()), argUsages))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@@ -35,6 +35,7 @@ import me.lucko.luckperms.common.model.PermissionHolder;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
@@ -114,7 +115,7 @@ public abstract class GenericChildCommand {
|
||||
.collect(Collectors.toList());
|
||||
|
||||
builder.append(Component.text(" - ", NamedTextColor.DARK_AQUA))
|
||||
.append(Component.join(Component.space(), argUsages))
|
||||
.append(Component.join(JoinConfiguration.separator(Component.space()), argUsages))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@@ -33,6 +33,7 @@ import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
@@ -70,7 +71,7 @@ public abstract class SingleCommand extends Command<Void> {
|
||||
.collect(Collectors.toList());
|
||||
|
||||
builder.append(Component.text(" - ", NamedTextColor.DARK_AQUA))
|
||||
.append(Component.join(Component.space(), argUsages))
|
||||
.append(Component.join(JoinConfiguration.separator(Component.space()), argUsages))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@@ -28,14 +28,14 @@ package me.lucko.luckperms.common.config;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import me.lucko.luckperms.common.cacheddata.metastack.SimpleMetaStackDefinition;
|
||||
import me.lucko.luckperms.common.cacheddata.metastack.StandardStackElements;
|
||||
import me.lucko.luckperms.common.cacheddata.type.SimpleMetaValueSelector;
|
||||
import me.lucko.luckperms.common.config.generic.KeyedConfiguration;
|
||||
import me.lucko.luckperms.common.config.generic.key.ConfigKey;
|
||||
import me.lucko.luckperms.common.config.generic.key.SimpleConfigKey;
|
||||
import me.lucko.luckperms.common.context.calculator.WorldNameRewriter;
|
||||
import me.lucko.luckperms.common.graph.TraversalAlgorithm;
|
||||
import me.lucko.luckperms.common.metastacking.SimpleMetaStackDefinition;
|
||||
import me.lucko.luckperms.common.metastacking.StandardStackElements;
|
||||
import me.lucko.luckperms.common.model.PrimaryGroupHolder;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.query.QueryOptionsBuilderImpl;
|
||||
@@ -370,16 +370,16 @@ public final class ConfigKeys {
|
||||
/**
|
||||
* Creates a new prefix MetaStack element based upon the configured values.
|
||||
*/
|
||||
public static final ConfigKey<MetaStackDefinition> PREFIX_FORMATTING_OPTIONS = key(l -> {
|
||||
List<String> format = l.getStringList("meta-formatting.prefix.format", new ArrayList<>());
|
||||
public static final ConfigKey<MetaStackDefinition> PREFIX_FORMATTING_OPTIONS = key(c -> {
|
||||
List<String> format = c.getStringList("meta-formatting.prefix.format", new ArrayList<>());
|
||||
if (format.isEmpty()) {
|
||||
format.add("highest");
|
||||
}
|
||||
String startSpacer = l.getString("meta-formatting.prefix.start-spacer", "");
|
||||
String middleSpacer = l.getString("meta-formatting.prefix.middle-spacer", " ");
|
||||
String endSpacer = l.getString("meta-formatting.prefix.end-spacer", "");
|
||||
String startSpacer = c.getString("meta-formatting.prefix.start-spacer", "");
|
||||
String middleSpacer = c.getString("meta-formatting.prefix.middle-spacer", " ");
|
||||
String endSpacer = c.getString("meta-formatting.prefix.end-spacer", "");
|
||||
DuplicateRemovalFunction duplicateRemovalFunction;
|
||||
switch (l.getString("meta-formatting.prefix.duplicates", "").toLowerCase(Locale.ROOT)) {
|
||||
switch (c.getString("meta-formatting.prefix.duplicates", "").toLowerCase(Locale.ROOT)) {
|
||||
case "first-only":
|
||||
duplicateRemovalFunction = DuplicateRemovalFunction.FIRST_ONLY;
|
||||
break;
|
||||
@@ -391,22 +391,22 @@ public final class ConfigKeys {
|
||||
break;
|
||||
}
|
||||
|
||||
return new SimpleMetaStackDefinition(StandardStackElements.parseList(l.getPlugin(), format), duplicateRemovalFunction, startSpacer, middleSpacer, endSpacer);
|
||||
return new SimpleMetaStackDefinition(StandardStackElements.parseList(c.getPlugin(), format), duplicateRemovalFunction, startSpacer, middleSpacer, endSpacer);
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a new suffix MetaStack element based upon the configured values.
|
||||
*/
|
||||
public static final ConfigKey<MetaStackDefinition> SUFFIX_FORMATTING_OPTIONS = key(l -> {
|
||||
List<String> format = l.getStringList("meta-formatting.suffix.format", new ArrayList<>());
|
||||
public static final ConfigKey<MetaStackDefinition> SUFFIX_FORMATTING_OPTIONS = key(c -> {
|
||||
List<String> format = c.getStringList("meta-formatting.suffix.format", new ArrayList<>());
|
||||
if (format.isEmpty()) {
|
||||
format.add("highest");
|
||||
}
|
||||
String startSpacer = l.getString("meta-formatting.suffix.start-spacer", "");
|
||||
String middleSpacer = l.getString("meta-formatting.suffix.middle-spacer", " ");
|
||||
String endSpacer = l.getString("meta-formatting.suffix.end-spacer", "");
|
||||
String startSpacer = c.getString("meta-formatting.suffix.start-spacer", "");
|
||||
String middleSpacer = c.getString("meta-formatting.suffix.middle-spacer", " ");
|
||||
String endSpacer = c.getString("meta-formatting.suffix.end-spacer", "");
|
||||
DuplicateRemovalFunction duplicateRemovalFunction;
|
||||
switch (l.getString("meta-formatting.suffix.duplicates", "").toLowerCase(Locale.ROOT)) {
|
||||
switch (c.getString("meta-formatting.suffix.duplicates", "").toLowerCase(Locale.ROOT)) {
|
||||
case "first-only":
|
||||
duplicateRemovalFunction = DuplicateRemovalFunction.FIRST_ONLY;
|
||||
break;
|
||||
@@ -418,7 +418,7 @@ public final class ConfigKeys {
|
||||
break;
|
||||
}
|
||||
|
||||
return new SimpleMetaStackDefinition(StandardStackElements.parseList(l.getPlugin(), format), duplicateRemovalFunction, startSpacer, middleSpacer, endSpacer);
|
||||
return new SimpleMetaStackDefinition(StandardStackElements.parseList(c.getPlugin(), format), duplicateRemovalFunction, startSpacer, middleSpacer, endSpacer);
|
||||
});
|
||||
|
||||
/**
|
||||
|
@@ -138,7 +138,7 @@ public enum DependencyRepository {
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the the {@code dependency} to the {@code file}, ensuring the
|
||||
* Downloads the {@code dependency} to the {@code file}, ensuring the
|
||||
* downloaded bytes match the checksum.
|
||||
*
|
||||
* @param dependency the dependency to download
|
||||
|
@@ -210,12 +210,17 @@ public enum ShorthandParser {
|
||||
* Implements an iterator over a given range of ints.
|
||||
*/
|
||||
private abstract static class RangeIterator implements Iterator<String> {
|
||||
private static final int MAX_RANGE = 250;
|
||||
|
||||
private final int max;
|
||||
private int next;
|
||||
|
||||
RangeIterator(int a, int b) {
|
||||
this.max = Math.max(a, b);
|
||||
this.next = Math.min(a, b);
|
||||
if ((this.max - this.next) > MAX_RANGE) {
|
||||
throw new IllegalArgumentException("Range too large");
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract String toString(int i);
|
||||
|
@@ -61,6 +61,7 @@ import me.lucko.luckperms.common.storage.misc.DataConstraints;
|
||||
import me.lucko.luckperms.common.tasks.CacheHousekeepingTask;
|
||||
import me.lucko.luckperms.common.tasks.ExpireTemporaryTask;
|
||||
import me.lucko.luckperms.common.tasks.SyncTask;
|
||||
import me.lucko.luckperms.common.treeview.AsyncPermissionRegistry;
|
||||
import me.lucko.luckperms.common.treeview.PermissionRegistry;
|
||||
import me.lucko.luckperms.common.verbose.VerboseHandler;
|
||||
import me.lucko.luckperms.common.webeditor.socket.WebEditorSocket;
|
||||
@@ -92,7 +93,7 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
||||
// init during load
|
||||
private DependencyManager dependencyManager;
|
||||
private TranslationManager translationManager;
|
||||
private PermissionRegistry permissionRegistry;
|
||||
private AsyncPermissionRegistry permissionRegistry;
|
||||
private VerboseHandler verboseHandler;
|
||||
|
||||
// init during enable
|
||||
@@ -128,7 +129,7 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
||||
this.translationManager.reload();
|
||||
|
||||
// load some utilities early
|
||||
this.permissionRegistry = new PermissionRegistry(getBootstrap().getScheduler());
|
||||
this.permissionRegistry = new AsyncPermissionRegistry(getBootstrap().getScheduler());
|
||||
this.verboseHandler = new VerboseHandler(getBootstrap().getScheduler());
|
||||
}
|
||||
|
||||
|
@@ -54,7 +54,7 @@ final class FlagUtils {
|
||||
private static byte toByte0(Set<Flag> settings) {
|
||||
byte b = 0;
|
||||
for (Flag setting : settings) {
|
||||
b |= 1 << setting.ordinal();
|
||||
b |= (byte) (1 << setting.ordinal());
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
@@ -56,7 +56,7 @@ public class QueryOptionsImpl implements QueryOptions {
|
||||
// computed based on state above
|
||||
private final int hashCode;
|
||||
private Set<Flag> flagsSet = null;
|
||||
private final ContextSatisfyMode contextSatisfyMode;
|
||||
private final ContextSatisfyMode overrideContextSatisfyMode;
|
||||
|
||||
QueryOptionsImpl(QueryMode mode, @Nullable ImmutableContextSet context, byte flags, @Nullable Map<OptionKey<?>, Object> options) {
|
||||
this.mode = mode;
|
||||
@@ -65,7 +65,7 @@ public class QueryOptionsImpl implements QueryOptions {
|
||||
this.options = options == null ? null : ImmutableMap.copyOf(options);
|
||||
|
||||
this.hashCode = calculateHashCode();
|
||||
this.contextSatisfyMode = options == null ? null : (ContextSatisfyMode) options.get(ContextSatisfyMode.KEY);
|
||||
this.overrideContextSatisfyMode = options == null ? null : (ContextSatisfyMode) options.get(ContextSatisfyMode.KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,7 +119,7 @@ public class QueryOptionsImpl implements QueryOptions {
|
||||
public boolean satisfies(@NonNull ContextSet contextSet, @NonNull ContextSatisfyMode defaultContextSatisfyMode) {
|
||||
switch (this.mode) {
|
||||
case CONTEXTUAL:
|
||||
return contextSet.isSatisfiedBy(this.context, this.contextSatisfyMode == null ? defaultContextSatisfyMode : this.contextSatisfyMode);
|
||||
return contextSet.isSatisfiedBy(this.context, this.overrideContextSatisfyMode == null ? defaultContextSatisfyMode : this.overrideContextSatisfyMode);
|
||||
case NON_CONTEXTUAL:
|
||||
return true;
|
||||
default:
|
||||
|
@@ -28,6 +28,7 @@ package me.lucko.luckperms.common.sender;
|
||||
import com.google.common.collect.Iterables;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.luckperms.api.util.Tristate;
|
||||
|
||||
@@ -155,7 +156,7 @@ public final class AbstractSender<T> implements Sender {
|
||||
case 1:
|
||||
return input.get(0);
|
||||
default:
|
||||
return Component.join(Component.empty(), input);
|
||||
return Component.join(JoinConfiguration.separator(Component.empty()), input);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* 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.treeview;
|
||||
|
||||
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||
import me.lucko.luckperms.common.plugin.scheduler.SchedulerTask;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class AsyncPermissionRegistry extends PermissionRegistry implements AutoCloseable {
|
||||
|
||||
/** A queue of permission strings to be added to the tree */
|
||||
private final Queue<String> queue;
|
||||
/** The tick task */
|
||||
private final SchedulerTask task;
|
||||
|
||||
public AsyncPermissionRegistry(SchedulerAdapter scheduler) {
|
||||
this.queue = new ConcurrentLinkedQueue<>();
|
||||
this.task = scheduler.asyncRepeating(this::tick, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void offer(String permission) {
|
||||
if (permission == null) {
|
||||
throw new NullPointerException("permission");
|
||||
}
|
||||
this.queue.offer(permission);
|
||||
}
|
||||
|
||||
private void tick() {
|
||||
for (String e; (e = this.queue.poll()) != null; ) {
|
||||
try {
|
||||
doInsert(e);
|
||||
} catch (Exception ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.task.cancel();
|
||||
}
|
||||
|
||||
}
|
@@ -26,35 +26,20 @@
|
||||
package me.lucko.luckperms.common.treeview;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
|
||||
import me.lucko.luckperms.common.plugin.scheduler.SchedulerTask;
|
||||
import me.lucko.luckperms.common.util.ImmutableCollectors;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Stores a collection of all permissions known to the platform.
|
||||
*/
|
||||
public class PermissionRegistry implements AutoCloseable {
|
||||
public class PermissionRegistry {
|
||||
private static final Splitter DOT_SPLIT = Splitter.on('.').omitEmptyStrings();
|
||||
|
||||
/** The root node in the tree */
|
||||
private final TreeNode rootNode;
|
||||
/** A queue of permission strings to be added to the tree */
|
||||
private final Queue<String> queue;
|
||||
/** The tick task */
|
||||
private final SchedulerTask task;
|
||||
|
||||
public PermissionRegistry(SchedulerAdapter scheduler) {
|
||||
this.rootNode = new TreeNode();
|
||||
this.queue = new ConcurrentLinkedQueue<>();
|
||||
this.task = scheduler.asyncRepeating(this::tick, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
private final TreeNode rootNode = new TreeNode();
|
||||
|
||||
public TreeNode getRootNode() {
|
||||
return this.rootNode;
|
||||
@@ -66,33 +51,33 @@ public class PermissionRegistry implements AutoCloseable {
|
||||
.collect(ImmutableCollectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Offer a permission to the registry (to be potentially inserted asynchronously).
|
||||
*
|
||||
* @param permission the permission
|
||||
*/
|
||||
public void offer(String permission) {
|
||||
insert(permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a permission into the registry.
|
||||
*
|
||||
* @param permission the permission
|
||||
*/
|
||||
public void insert(String permission) {
|
||||
if (permission == null) {
|
||||
throw new NullPointerException("permission");
|
||||
}
|
||||
this.queue.offer(permission);
|
||||
}
|
||||
|
||||
private void tick() {
|
||||
for (String e; (e = this.queue.poll()) != null; ) {
|
||||
insert(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.task.cancel();
|
||||
}
|
||||
|
||||
public void insert(String permission) {
|
||||
try {
|
||||
doInsert(permission);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
private void doInsert(String permission) {
|
||||
protected void doInsert(String permission) {
|
||||
permission = permission.toLowerCase(Locale.ROOT);
|
||||
|
||||
// split the permission up into parts
|
||||
|
@@ -30,6 +30,7 @@ import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
@@ -72,7 +73,7 @@ public class DurationFormatter {
|
||||
* @return the formatted string
|
||||
*/
|
||||
public String formatString(Duration duration) {
|
||||
return PlainComponentSerializer.plain().serialize(TranslationManager.render(format(duration)));
|
||||
return PlainTextComponentSerializer.plainText().serialize(TranslationManager.render(format(duration)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -43,6 +43,7 @@ import me.lucko.luckperms.common.verbose.event.PermissionCheckEvent;
|
||||
import me.lucko.luckperms.common.verbose.event.VerboseEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.ComponentLike;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.luckperms.api.cacheddata.Result;
|
||||
import net.luckperms.api.node.Node;
|
||||
@@ -222,7 +223,7 @@ public class VerboseListener {
|
||||
}
|
||||
|
||||
// send the message
|
||||
HoverEvent<Component> hoverEvent = HoverEvent.showText(Component.join(Component.newline(), hover));
|
||||
HoverEvent<Component> hoverEvent = HoverEvent.showText(Component.join(JoinConfiguration.newlines(), hover));
|
||||
this.notifiedSender.sendMessage(component.hoverEvent(hoverEvent));
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* 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.cacheddata;
|
||||
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import me.lucko.luckperms.common.cacheddata.metastack.SimpleMetaStackDefinition;
|
||||
import me.lucko.luckperms.common.cacheddata.metastack.StandardStackElements;
|
||||
import me.lucko.luckperms.common.cacheddata.result.IntegerResult;
|
||||
import me.lucko.luckperms.common.cacheddata.result.StringResult;
|
||||
import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator;
|
||||
import me.lucko.luckperms.common.node.types.DisplayName;
|
||||
import me.lucko.luckperms.common.node.types.Meta;
|
||||
import me.lucko.luckperms.common.node.types.Prefix;
|
||||
import me.lucko.luckperms.common.node.types.Suffix;
|
||||
import me.lucko.luckperms.common.node.types.Weight;
|
||||
import net.luckperms.api.metastacking.DuplicateRemovalFunction;
|
||||
import net.luckperms.api.metastacking.MetaStackDefinition;
|
||||
import net.luckperms.api.node.ChatMetaType;
|
||||
import net.luckperms.api.node.types.MetaNode;
|
||||
import net.luckperms.api.node.types.PrefixNode;
|
||||
import net.luckperms.api.node.types.SuffixNode;
|
||||
import net.luckperms.api.node.types.WeightNode;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.shaded.com.google.common.collect.ImmutableList;
|
||||
import org.testcontainers.shaded.com.google.common.collect.ImmutableSet;
|
||||
|
||||
import java.util.SortedMap;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class MetaAccumulatorTest {
|
||||
|
||||
@Test
|
||||
public void testStates() {
|
||||
SimpleMetaStackDefinition definition = new SimpleMetaStackDefinition(ImmutableList.of(StandardStackElements.HIGHEST), DuplicateRemovalFunction.RETAIN_ALL, "", "", "");
|
||||
MetaAccumulator accumulator = new MetaAccumulator(definition, definition);
|
||||
|
||||
assertThrows(IllegalStateException.class, accumulator::getMeta);
|
||||
assertThrows(IllegalStateException.class, () -> accumulator.getChatMeta(ChatMetaType.PREFIX));
|
||||
assertThrows(IllegalStateException.class, accumulator::getPrefixes);
|
||||
assertThrows(IllegalStateException.class, accumulator::getSuffixes);
|
||||
assertThrows(IllegalStateException.class, accumulator::getWeight);
|
||||
assertThrows(IllegalStateException.class, accumulator::getPrimaryGroup);
|
||||
assertThrows(IllegalStateException.class, accumulator::getPrefixDefinition);
|
||||
assertThrows(IllegalStateException.class, accumulator::getSuffixDefinition);
|
||||
assertThrows(IllegalStateException.class, accumulator::getPrefix);
|
||||
assertThrows(IllegalStateException.class, accumulator::getSuffix);
|
||||
|
||||
Prefix prefixNode = Prefix.builder("hello", 100).build();
|
||||
|
||||
accumulator.accumulateNode(prefixNode);
|
||||
accumulator.complete();
|
||||
|
||||
assertThrows(IllegalStateException.class, () -> accumulator.accumulateNode(prefixNode));
|
||||
|
||||
StringResult<PrefixNode> prefixResult = accumulator.getPrefix();
|
||||
assertEquals(prefixNode, prefixResult.node());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmpty() {
|
||||
SimpleMetaStackDefinition definition = new SimpleMetaStackDefinition(ImmutableList.of(StandardStackElements.HIGHEST), DuplicateRemovalFunction.RETAIN_ALL, "[", "|", "]");
|
||||
MetaAccumulator accumulator = new MetaAccumulator(definition, definition);
|
||||
accumulator.complete();
|
||||
|
||||
ListMultimap<String, StringResult<MetaNode>> meta = accumulator.getMeta();
|
||||
assertEquals(0, meta.size());
|
||||
|
||||
SortedMap<Integer, StringResult<PrefixNode>> prefixes = accumulator.getPrefixes();
|
||||
assertEquals(0, prefixes.size());
|
||||
|
||||
SortedMap<Integer, StringResult<SuffixNode>> suffixes = accumulator.getSuffixes();
|
||||
assertEquals(0, suffixes.size());
|
||||
|
||||
IntegerResult<WeightNode> weight = accumulator.getWeight();
|
||||
assertTrue(weight.isNull());
|
||||
assertEquals(0, weight.intResult());
|
||||
assertNull(weight.node());
|
||||
|
||||
String primaryGroup = accumulator.getPrimaryGroup();
|
||||
assertNull(primaryGroup);
|
||||
|
||||
MetaStackDefinition prefixDefinition = accumulator.getPrefixDefinition();
|
||||
assertSame(definition, prefixDefinition);
|
||||
|
||||
MetaStackDefinition suffixDefinition = accumulator.getSuffixDefinition();
|
||||
assertSame(definition, suffixDefinition);
|
||||
|
||||
StringResult<PrefixNode> prefix = accumulator.getPrefix();
|
||||
assertNull(prefix.result());
|
||||
assertNull(prefix.node());
|
||||
|
||||
StringResult<SuffixNode> suffix = accumulator.getSuffix();
|
||||
assertNull(suffix.result());
|
||||
assertNull(suffix.node());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimple() {
|
||||
SimpleMetaStackDefinition definition = new SimpleMetaStackDefinition(ImmutableList.of(StandardStackElements.HIGHEST), DuplicateRemovalFunction.RETAIN_ALL, "[", "|", "]");
|
||||
MetaAccumulator accumulator = new MetaAccumulator(definition, definition);
|
||||
|
||||
accumulator.accumulateNode(Prefix.builder("b", 90).build());
|
||||
accumulator.accumulateNode(Prefix.builder("a", 100).build());
|
||||
accumulator.accumulateNode(Prefix.builder("c", 80).build());
|
||||
accumulator.accumulateNode(Suffix.builder("foo", 80).build());
|
||||
accumulator.accumulateNode(Meta.builder().key("foo").value("bar").build());
|
||||
accumulator.accumulateNode(Weight.builder(10).build()); // ignored
|
||||
accumulator.accumulateNode(DisplayName.builder("hello").build());
|
||||
accumulator.accumulateWeight(IntegerResult.of(Weight.builder(5).build()));
|
||||
accumulator.setPrimaryGroup("member");
|
||||
|
||||
accumulator.complete();
|
||||
|
||||
StringResult<PrefixNode> prefix = accumulator.getPrefix();
|
||||
assertEquals("[a]", prefix.result());
|
||||
|
||||
SortedMap<Integer, StringResult<PrefixNode>> prefixes = accumulator.getPrefixes();
|
||||
assertEquals(ImmutableSet.of(100, 90, 80), prefixes.keySet());
|
||||
|
||||
StringResult<SuffixNode> suffix = accumulator.getSuffix();
|
||||
assertEquals("[foo]", suffix.result());
|
||||
|
||||
SortedMap<Integer, StringResult<SuffixNode>> suffixes = accumulator.getSuffixes();
|
||||
assertEquals(ImmutableSet.of(80), suffixes.keySet());
|
||||
|
||||
ListMultimap<String, StringResult<MetaNode>> meta = accumulator.getMeta();
|
||||
assertEquals(3, meta.size());
|
||||
assertEquals(ImmutableSet.of("foo", "weight", "primarygroup"), meta.keySet());
|
||||
assertEquals("bar", meta.get("foo").get(0).result());
|
||||
assertEquals("5", meta.get("weight").get(0).result());
|
||||
assertEquals("member", meta.get("primarygroup").get(0).result());
|
||||
|
||||
IntegerResult<WeightNode> weight = accumulator.getWeight();
|
||||
assertEquals(5, weight.intResult());
|
||||
|
||||
String primaryGroup = accumulator.getPrimaryGroup();
|
||||
assertEquals("member", primaryGroup);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* 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.cacheddata;
|
||||
|
||||
import me.lucko.luckperms.common.cacheddata.metastack.SimpleMetaStackDefinition;
|
||||
import me.lucko.luckperms.common.cacheddata.metastack.StandardStackElements;
|
||||
import me.lucko.luckperms.common.cacheddata.result.StringResult;
|
||||
import me.lucko.luckperms.common.cacheddata.type.MetaStackAccumulator;
|
||||
import me.lucko.luckperms.common.node.types.Prefix;
|
||||
import net.luckperms.api.metastacking.DuplicateRemovalFunction;
|
||||
import net.luckperms.api.node.ChatMetaType;
|
||||
import net.luckperms.api.node.types.PrefixNode;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.shaded.com.google.common.collect.ImmutableList;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
public class MetaStackAccumulatorTest {
|
||||
|
||||
@Test
|
||||
public void testEmpty() {
|
||||
SimpleMetaStackDefinition definition = new SimpleMetaStackDefinition(ImmutableList.of(StandardStackElements.HIGHEST), DuplicateRemovalFunction.RETAIN_ALL, "", "", "");
|
||||
MetaStackAccumulator<PrefixNode> accumulator = new MetaStackAccumulator<>(definition, ChatMetaType.PREFIX);
|
||||
|
||||
StringResult<PrefixNode> result = accumulator.toResult();
|
||||
assertNotNull(result);
|
||||
assertNull(result.result());
|
||||
assertNull(result.node());
|
||||
assertNull(result.overriddenResult());
|
||||
|
||||
String formattedString = accumulator.toFormattedString();
|
||||
assertNull(formattedString);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingle() {
|
||||
SimpleMetaStackDefinition definition = new SimpleMetaStackDefinition(ImmutableList.of(StandardStackElements.HIGHEST), DuplicateRemovalFunction.RETAIN_ALL, "[", "|", "]");
|
||||
MetaStackAccumulator<PrefixNode> accumulator = new MetaStackAccumulator<>(definition, ChatMetaType.PREFIX);
|
||||
|
||||
PrefixNode a = Prefix.builder("a", 100).build();
|
||||
PrefixNode b = Prefix.builder("b", 90).build();
|
||||
PrefixNode c = Prefix.builder("c", 80).build();
|
||||
|
||||
accumulator.offer(b);
|
||||
accumulator.offer(a);
|
||||
accumulator.offer(c);
|
||||
|
||||
StringResult<PrefixNode> result = accumulator.toResult();
|
||||
assertNotNull(result);
|
||||
assertEquals("[a]", result.result());
|
||||
assertEquals(a, result.node());
|
||||
assertNull(result.overriddenResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiple() {
|
||||
SimpleMetaStackDefinition definition = new SimpleMetaStackDefinition(ImmutableList.of(StandardStackElements.LOWEST, StandardStackElements.HIGHEST), DuplicateRemovalFunction.RETAIN_ALL, "[", "|", "]");
|
||||
MetaStackAccumulator<PrefixNode> accumulator = new MetaStackAccumulator<>(definition, ChatMetaType.PREFIX);
|
||||
|
||||
PrefixNode a = Prefix.builder("a", 100).build();
|
||||
PrefixNode b = Prefix.builder("b", 90).build();
|
||||
PrefixNode c = Prefix.builder("c", 80).build();
|
||||
|
||||
accumulator.offer(b);
|
||||
accumulator.offer(a);
|
||||
accumulator.offer(c);
|
||||
|
||||
StringResult<PrefixNode> result = accumulator.toResult();
|
||||
assertNotNull(result);
|
||||
assertEquals("[c|a]", result.result());
|
||||
assertEquals(c, result.node());
|
||||
|
||||
StringResult<PrefixNode> overriddenResult = result.overriddenResult();
|
||||
assertNotNull(overriddenResult);
|
||||
assertEquals(a, overriddenResult.node());
|
||||
assertNull(overriddenResult.overriddenResult());
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* 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.cacheddata;
|
||||
|
||||
import me.lucko.luckperms.common.cacheddata.metastack.StandardStackElements;
|
||||
import me.lucko.luckperms.common.model.HolderType;
|
||||
import me.lucko.luckperms.common.model.InheritanceOrigin;
|
||||
import me.lucko.luckperms.common.model.PermissionHolderIdentifier;
|
||||
import me.lucko.luckperms.common.model.Track;
|
||||
import me.lucko.luckperms.common.model.manager.track.StandardTrackManager;
|
||||
import me.lucko.luckperms.common.model.manager.track.TrackManager;
|
||||
import me.lucko.luckperms.common.node.types.Prefix;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import net.luckperms.api.metastacking.MetaStackElement;
|
||||
import net.luckperms.api.model.data.DataType;
|
||||
import net.luckperms.api.node.ChatMetaType;
|
||||
import net.luckperms.api.node.metadata.types.InheritanceOriginMetadata;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.shaded.com.google.common.collect.ImmutableList;
|
||||
|
||||
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;
|
||||
|
||||
public class MetaStackElementTest {
|
||||
|
||||
@Test
|
||||
public void testHighest() {
|
||||
MetaStackElement highest = StandardStackElements.HIGHEST;
|
||||
assertTrue(highest.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).build(), // node
|
||||
null // current
|
||||
));
|
||||
assertFalse(highest.shouldAccumulate(
|
||||
ChatMetaType.SUFFIX,
|
||||
Prefix.builder("foo", 100).build(), // node
|
||||
null // current
|
||||
));
|
||||
assertTrue(highest.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).build(), // node
|
||||
Prefix.builder("bar", 50).build()) // current
|
||||
);
|
||||
assertFalse(highest.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 50).build(), // node
|
||||
Prefix.builder("bar", 100).build()) // current
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLowest() {
|
||||
MetaStackElement lowest = StandardStackElements.LOWEST;
|
||||
assertTrue(lowest.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).build(), // node
|
||||
null // current
|
||||
));
|
||||
assertFalse(lowest.shouldAccumulate(
|
||||
ChatMetaType.SUFFIX,
|
||||
Prefix.builder("foo", 100).build(), // node
|
||||
null // current
|
||||
));
|
||||
assertTrue(lowest.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 50).build(), // node
|
||||
Prefix.builder("bar", 100).build()) // current
|
||||
);
|
||||
assertFalse(lowest.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).build(), // node
|
||||
Prefix.builder("bar", 50).build()) // current
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHighestOwn() {
|
||||
InheritanceOrigin userOrigin = new InheritanceOrigin(new PermissionHolderIdentifier(HolderType.USER, ""), DataType.NORMAL);
|
||||
InheritanceOrigin groupOrigin = new InheritanceOrigin(new PermissionHolderIdentifier(HolderType.GROUP, ""), DataType.NORMAL);
|
||||
|
||||
MetaStackElement highestOwn = StandardStackElements.HIGHEST_OWN;
|
||||
assertTrue(highestOwn.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).withMetadata(InheritanceOriginMetadata.KEY, userOrigin).build(), // node
|
||||
null // current
|
||||
));
|
||||
assertFalse(highestOwn.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).withMetadata(InheritanceOriginMetadata.KEY, groupOrigin).build(), // node
|
||||
null // current
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHighestInherited() {
|
||||
InheritanceOrigin userOrigin = new InheritanceOrigin(new PermissionHolderIdentifier(HolderType.USER, ""), DataType.NORMAL);
|
||||
InheritanceOrigin groupOrigin = new InheritanceOrigin(new PermissionHolderIdentifier(HolderType.GROUP, ""), DataType.NORMAL);
|
||||
|
||||
MetaStackElement highestInherited = StandardStackElements.HIGHEST_INHERITED;
|
||||
assertTrue(highestInherited.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).withMetadata(InheritanceOriginMetadata.KEY, groupOrigin).build(), // node
|
||||
null // current
|
||||
));
|
||||
assertFalse(highestInherited.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).withMetadata(InheritanceOriginMetadata.KEY, userOrigin).build(), // node
|
||||
null // current
|
||||
));
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Test
|
||||
public void testHighestFromGroupOnTrack() {
|
||||
LuckPermsPlugin plugin = mock(LuckPermsPlugin.class);
|
||||
TrackManager<Track> trackManager = new StandardTrackManager(plugin);
|
||||
when(plugin.getTrackManager()).thenReturn((TrackManager) trackManager);
|
||||
|
||||
Track track = trackManager.getOrMake("test");
|
||||
track.setGroups(ImmutableList.of("foo", "bar"));
|
||||
|
||||
InheritanceOrigin fooOrigin = new InheritanceOrigin(new PermissionHolderIdentifier(HolderType.GROUP, "foo"), DataType.NORMAL);
|
||||
InheritanceOrigin bazOrigin = new InheritanceOrigin(new PermissionHolderIdentifier(HolderType.GROUP, "baz"), DataType.NORMAL);
|
||||
|
||||
MetaStackElement highestFromGroupOnTrack = StandardStackElements.highestFromGroupOnTrack(plugin, "test");
|
||||
assertTrue(highestFromGroupOnTrack.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).withMetadata(InheritanceOriginMetadata.KEY, fooOrigin).build(), // node
|
||||
null // current
|
||||
));
|
||||
assertFalse(highestFromGroupOnTrack.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).withMetadata(InheritanceOriginMetadata.KEY, bazOrigin).build(), // node
|
||||
null // current
|
||||
));
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Test
|
||||
public void testHighestNotFromGroupOnTrack() {
|
||||
LuckPermsPlugin plugin = mock(LuckPermsPlugin.class);
|
||||
TrackManager<Track> trackManager = new StandardTrackManager(plugin);
|
||||
when(plugin.getTrackManager()).thenReturn((TrackManager) trackManager);
|
||||
|
||||
Track track = trackManager.getOrMake("test");
|
||||
track.setGroups(ImmutableList.of("foo", "bar"));
|
||||
|
||||
InheritanceOrigin fooOrigin = new InheritanceOrigin(new PermissionHolderIdentifier(HolderType.GROUP, "foo"), DataType.NORMAL);
|
||||
InheritanceOrigin bazOrigin = new InheritanceOrigin(new PermissionHolderIdentifier(HolderType.GROUP, "baz"), DataType.NORMAL);
|
||||
InheritanceOrigin userOrigin = new InheritanceOrigin(new PermissionHolderIdentifier(HolderType.USER, "foo"), DataType.NORMAL);
|
||||
|
||||
MetaStackElement highestNotFromGroupOnTrack = StandardStackElements.highestNotFromGroupOnTrack(plugin, "test");
|
||||
assertTrue(highestNotFromGroupOnTrack.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).withMetadata(InheritanceOriginMetadata.KEY, userOrigin).build(), // node
|
||||
null // current
|
||||
));
|
||||
assertTrue(highestNotFromGroupOnTrack.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).withMetadata(InheritanceOriginMetadata.KEY, bazOrigin).build(), // node
|
||||
null // current
|
||||
));
|
||||
assertFalse(highestNotFromGroupOnTrack.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).withMetadata(InheritanceOriginMetadata.KEY, fooOrigin).build(), // node
|
||||
null // current
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHighestFromGroup() {
|
||||
InheritanceOrigin fooOrigin = new InheritanceOrigin(new PermissionHolderIdentifier(HolderType.GROUP, "foo"), DataType.NORMAL);
|
||||
InheritanceOrigin bazOrigin = new InheritanceOrigin(new PermissionHolderIdentifier(HolderType.GROUP, "baz"), DataType.NORMAL);
|
||||
InheritanceOrigin userOrigin = new InheritanceOrigin(new PermissionHolderIdentifier(HolderType.USER, "foo"), DataType.NORMAL);
|
||||
|
||||
MetaStackElement highestFromGroup = StandardStackElements.highestFromGroup("foo");
|
||||
assertTrue(highestFromGroup.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).withMetadata(InheritanceOriginMetadata.KEY, fooOrigin).build(), // node
|
||||
null // current
|
||||
));
|
||||
assertFalse(highestFromGroup.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).withMetadata(InheritanceOriginMetadata.KEY, bazOrigin).build(), // node
|
||||
null // current
|
||||
));
|
||||
assertFalse(highestFromGroup.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).withMetadata(InheritanceOriginMetadata.KEY, userOrigin).build(), // node
|
||||
null // current
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHighestNotFromGroup() {
|
||||
InheritanceOrigin fooOrigin = new InheritanceOrigin(new PermissionHolderIdentifier(HolderType.GROUP, "foo"), DataType.NORMAL);
|
||||
InheritanceOrigin bazOrigin = new InheritanceOrigin(new PermissionHolderIdentifier(HolderType.GROUP, "baz"), DataType.NORMAL);
|
||||
InheritanceOrigin userOrigin = new InheritanceOrigin(new PermissionHolderIdentifier(HolderType.USER, "foo"), DataType.NORMAL);
|
||||
|
||||
MetaStackElement highestNotFromGroup = StandardStackElements.highestNotFromGroup("foo");
|
||||
assertTrue(highestNotFromGroup.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).withMetadata(InheritanceOriginMetadata.KEY, userOrigin).build(), // node
|
||||
null // current
|
||||
));
|
||||
assertTrue(highestNotFromGroup.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).withMetadata(InheritanceOriginMetadata.KEY, bazOrigin).build(), // node
|
||||
null // current
|
||||
));
|
||||
assertFalse(highestNotFromGroup.shouldAccumulate(
|
||||
ChatMetaType.PREFIX,
|
||||
Prefix.builder("foo", 100).withMetadata(InheritanceOriginMetadata.KEY, fooOrigin).build(), // node
|
||||
null // current
|
||||
));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* 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.cacheddata;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import me.lucko.luckperms.common.cacheddata.result.StringResult;
|
||||
import me.lucko.luckperms.common.cacheddata.type.SimpleMetaValueSelector;
|
||||
import me.lucko.luckperms.common.cacheddata.type.SimpleMetaValueSelector.Strategy;
|
||||
import net.luckperms.api.cacheddata.Result;
|
||||
import net.luckperms.api.node.types.MetaNode;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class MetaValueSelectorTest {
|
||||
|
||||
@Test
|
||||
public void testStrategies() {
|
||||
Map<String, Strategy> strategies = ImmutableMap.of(
|
||||
"foo", Strategy.HIGHEST_NUMBER,
|
||||
"bar", Strategy.LOWEST_NUMBER
|
||||
);
|
||||
SimpleMetaValueSelector selector = new SimpleMetaValueSelector(strategies, Strategy.INHERITANCE);
|
||||
|
||||
// empty
|
||||
assertThrows(IllegalArgumentException.class, () -> selector.selectValue("hello", ImmutableList.of()));
|
||||
|
||||
Result<String, MetaNode> foo = StringResult.of("foo");
|
||||
|
||||
// single value
|
||||
Result<String, MetaNode> value = selector.selectValue("abc", ImmutableList.of(foo));
|
||||
assertSame(foo, value);
|
||||
|
||||
// fallback to default when values are not numbers
|
||||
value = selector.selectValue("foo", ImmutableList.of(foo));
|
||||
assertSame(foo, value);
|
||||
|
||||
Result<String, MetaNode> one = StringResult.of("1");
|
||||
Result<String, MetaNode> two = StringResult.of("2");
|
||||
Result<String, MetaNode> three = StringResult.of("3");
|
||||
ImmutableList<Result<String, MetaNode>> values = ImmutableList.of(two, one, three);
|
||||
|
||||
// first value
|
||||
assertSame(two, selector.selectValue("abc", values));
|
||||
|
||||
// highest value
|
||||
assertSame(three, selector.selectValue("foo", values));
|
||||
|
||||
// lowest value
|
||||
assertSame(one, selector.selectValue("bar", values));
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* 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.cacheddata;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class UsageTrackedTest {
|
||||
|
||||
@Test
|
||||
public void testUsedRecently() {
|
||||
TestUsageTracked usageTracked = new TestUsageTracked();
|
||||
assertTrue(usageTracked.usedInTheLast(1, TimeUnit.MINUTES));
|
||||
usageTracked.recordUsage();
|
||||
assertTrue(usageTracked.usedInTheLast(1, TimeUnit.MINUTES));
|
||||
|
||||
usageTracked.setLastUsed(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1));
|
||||
assertFalse(usageTracked.usedInTheLast(1, TimeUnit.MINUTES));
|
||||
}
|
||||
|
||||
static final class TestUsageTracked extends UsageTracked {
|
||||
void setLastUsed(long lastUsed) {
|
||||
this.lastUsed = lastUsed;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -78,6 +78,21 @@ public class FilterMongoTest {
|
||||
),
|
||||
// {"$or": [{"foo": "hello"}, {"bar": "world"}]}
|
||||
"{\"$or\": [{\"foo\": \"hello\"}, {\"bar\": \"world\"}]}"
|
||||
),
|
||||
Arguments.of(
|
||||
FilterList.or(
|
||||
TestField.FOO.isEqualTo("hello", ConstraintFactory.STRINGS),
|
||||
TestField.BAR.isNotEqualTo("world", ConstraintFactory.STRINGS),
|
||||
TestField.BAZ.isSimilarTo("abc%xyz", ConstraintFactory.STRINGS),
|
||||
TestField.BAZ.isNotSimilarTo("a_c", ConstraintFactory.STRINGS)
|
||||
),
|
||||
// {"$or": [
|
||||
// {"foo": "hello"},
|
||||
// {"bar": {"$ne": "world"}},
|
||||
// {"baz": {"$regularExpression": {"pattern": "abc.*xyz", "options": "i"}}},
|
||||
// {"baz": {"$not": {"$regularExpression": {"pattern": "a.c", "options": "i"}}}}
|
||||
// ]}
|
||||
"{\"$or\": [{\"foo\": \"hello\"}, {\"bar\": {\"$ne\": \"world\"}}, {\"baz\": {\"$regularExpression\": {\"pattern\": \"abc.*xyz\", \"options\": \"i\"}}}, {\"baz\": {\"$not\": {\"$regularExpression\": {\"pattern\": \"a.c\", \"options\": \"i\"}}}}]}"
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -94,7 +109,7 @@ public class FilterMongoTest {
|
||||
}
|
||||
|
||||
private enum TestField implements FilterField<Object, String> {
|
||||
FOO, BAR;
|
||||
FOO, BAR, BAZ;
|
||||
|
||||
@Override
|
||||
public String getValue(Object object) {
|
||||
|
@@ -73,6 +73,16 @@ public class FilterSqlTest {
|
||||
),
|
||||
" WHERE foo = hello OR bar = world",
|
||||
" WHERE foo = ? OR bar = ?"
|
||||
),
|
||||
Arguments.of(
|
||||
FilterList.or(
|
||||
TestField.FOO.isEqualTo("hello", ConstraintFactory.STRINGS),
|
||||
TestField.BAR.isNotEqualTo("world", ConstraintFactory.STRINGS),
|
||||
TestField.BAZ.isSimilarTo("abc%xyz", ConstraintFactory.STRINGS),
|
||||
TestField.BAZ.isNotSimilarTo("a_c", ConstraintFactory.STRINGS)
|
||||
),
|
||||
" WHERE foo = hello OR bar != world OR baz LIKE abc%xyz OR baz NOT LIKE a_c",
|
||||
" WHERE foo = ? OR bar != ? OR baz LIKE ? OR baz NOT LIKE ?"
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -80,7 +90,7 @@ public class FilterSqlTest {
|
||||
@ParameterizedTest(name = "[{index}] {0}")
|
||||
@MethodSource
|
||||
public void testQueries(FilterList<Object> filters, String expectedSql, String expectedSqlParams) {
|
||||
TestFilterMongoBuilder sqlBuilder = new TestFilterMongoBuilder();
|
||||
FilterSqlBuilder<Object> sqlBuilder = new TestFilterSqlBuilder();
|
||||
sqlBuilder.visit(filters);
|
||||
|
||||
System.out.println(sqlBuilder.builder().toReadableString());
|
||||
@@ -91,7 +101,7 @@ public class FilterSqlTest {
|
||||
}
|
||||
|
||||
private enum TestField implements FilterField<Object, String> {
|
||||
FOO, BAR;
|
||||
FOO, BAR, BAZ;
|
||||
|
||||
@Override
|
||||
public String getValue(Object object) {
|
||||
@@ -104,7 +114,7 @@ public class FilterSqlTest {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class TestFilterMongoBuilder extends FilterSqlBuilder<Object> {
|
||||
private static final class TestFilterSqlBuilder extends FilterSqlBuilder<Object> {
|
||||
|
||||
@Override
|
||||
public void visitFieldName(FilterField<Object, ?> field) {
|
||||
|
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* 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.node;
|
||||
|
||||
import me.lucko.luckperms.common.model.HolderType;
|
||||
import me.lucko.luckperms.common.node.factory.NodeCommandFactory;
|
||||
import me.lucko.luckperms.common.node.types.Inheritance;
|
||||
import me.lucko.luckperms.common.node.types.Meta;
|
||||
import me.lucko.luckperms.common.node.types.Permission;
|
||||
import me.lucko.luckperms.common.node.types.Prefix;
|
||||
import net.luckperms.api.node.Node;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class NodeCommandFactoryTest {
|
||||
|
||||
private static Stream<Arguments> testUndoCommand() {
|
||||
return Stream.of(
|
||||
Arguments.of("group test permission unset test", Permission.builder().permission("test").build(), HolderType.GROUP, false),
|
||||
Arguments.of("user test permission unset test", Permission.builder().permission("test").build(), HolderType.USER, false),
|
||||
Arguments.of("user test permission unsettemp test", Permission.builder().permission("test").expiry(1, TimeUnit.HOURS).build(), HolderType.USER, false),
|
||||
Arguments.of("user test permission unset test server=foo world=bar", Permission.builder().permission("test").withContext("server", "foo").withContext("world", "bar").build(), HolderType.USER, false),
|
||||
Arguments.of("user test permission unset test global", Permission.builder().permission("test").build(), HolderType.USER, true),
|
||||
Arguments.of("user test parent remove test", Inheritance.builder().group("test").build(), HolderType.USER, false),
|
||||
Arguments.of("user test parent removetemp test", Inheritance.builder().group("test").expiry(1, TimeUnit.HOURS).build(), HolderType.USER, false),
|
||||
Arguments.of("user test meta removeprefix 100 test", Prefix.builder().priority(100).prefix("test").build(), HolderType.USER, false),
|
||||
Arguments.of("user test meta removetempprefix 100 test", Prefix.builder().priority(100).prefix("test").expiry(1, TimeUnit.HOURS).build(), HolderType.USER, false),
|
||||
Arguments.of("user test meta removeprefix 100 \"hello world\"", Prefix.builder().priority(100).prefix("hello world").build(), HolderType.USER, false),
|
||||
Arguments.of("user test meta unset foo", Meta.builder().key("foo").value("bar").build(), HolderType.USER, false),
|
||||
Arguments.of("user test meta unsettemp foo", Meta.builder().key("foo").value("bar").expiry(1, TimeUnit.HOURS).build(), HolderType.USER, false)
|
||||
);
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "[{index}] {0}")
|
||||
@MethodSource
|
||||
public void testUndoCommand(String expected, Node node, HolderType holderType, boolean explicitGlobalContext) {
|
||||
String result = NodeCommandFactory.undoCommand(node, "test", holderType, explicitGlobalContext);
|
||||
assertEquals(expected, result);
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* 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.node;
|
||||
|
||||
import me.lucko.luckperms.common.filter.Comparison;
|
||||
import me.lucko.luckperms.common.filter.Constraint;
|
||||
import me.lucko.luckperms.common.node.matcher.ConstraintNodeMatcher;
|
||||
import me.lucko.luckperms.common.node.matcher.StandardNodeMatchers;
|
||||
import me.lucko.luckperms.common.node.types.Permission;
|
||||
import net.luckperms.api.node.Node;
|
||||
import net.luckperms.api.node.NodeType;
|
||||
import net.luckperms.api.node.types.MetaNode;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class NodeMatcherTest {
|
||||
|
||||
@Test
|
||||
public void testKey() {
|
||||
ConstraintNodeMatcher<Node> matcher = StandardNodeMatchers.key("foo");
|
||||
Constraint<String> constraint = matcher.getConstraint();
|
||||
|
||||
assertEquals(Comparison.EQUAL, constraint.comparison());
|
||||
assertEquals("foo", constraint.value());
|
||||
|
||||
ConstraintNodeMatcher<Permission> typedMatcher = StandardNodeMatchers.key(Permission.builder().permission("foo").build());
|
||||
Constraint<String> typedConstraint = typedMatcher.getConstraint();
|
||||
|
||||
assertEquals(Comparison.EQUAL, typedConstraint.comparison());
|
||||
assertEquals("foo", typedConstraint.value());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"foo, foo%",
|
||||
})
|
||||
public void testKeyStartsWith(String value, String expectedConstraint) {
|
||||
ConstraintNodeMatcher<Node> matcher = StandardNodeMatchers.keyStartsWith(value);
|
||||
Constraint<String> constraint = matcher.getConstraint();
|
||||
|
||||
assertEquals(Comparison.SIMILAR, constraint.comparison());
|
||||
assertEquals(expectedConstraint, constraint.value());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"foo, meta.foo.%",
|
||||
})
|
||||
public void testMetaKey(String value, String expectedConstraint) {
|
||||
ConstraintNodeMatcher<MetaNode> matcher = StandardNodeMatchers.metaKey(value);
|
||||
Constraint<String> constraint = matcher.getConstraint();
|
||||
|
||||
assertEquals(Comparison.SIMILAR, constraint.comparison());
|
||||
assertEquals(expectedConstraint, constraint.value());
|
||||
}
|
||||
|
||||
|
||||
private static Stream<Arguments> testType() {
|
||||
return Stream.of(
|
||||
Arguments.of(NodeType.REGEX_PERMISSION, "r=%"),
|
||||
Arguments.of(NodeType.INHERITANCE, "group.%"),
|
||||
Arguments.of(NodeType.PREFIX, "prefix.%.%"),
|
||||
Arguments.of(NodeType.SUFFIX, "suffix.%.%"),
|
||||
Arguments.of(NodeType.META, "meta.%.%"),
|
||||
Arguments.of(NodeType.WEIGHT, "weight.%"),
|
||||
Arguments.of(NodeType.DISPLAY_NAME, "displayname.%")
|
||||
);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource
|
||||
public void testType(NodeType<?> type, String expectedValue) {
|
||||
ConstraintNodeMatcher<?> matcher = StandardNodeMatchers.type(type);
|
||||
Constraint<String> constraint = matcher.getConstraint();
|
||||
|
||||
assertEquals(Comparison.SIMILAR, constraint.comparison());
|
||||
assertEquals(expectedValue, constraint.value());
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -139,7 +139,9 @@ public class NodeParseTest {
|
||||
"prefix.0.hello, 0, hello",
|
||||
"prefix.100.hello world, 100, hello world",
|
||||
"prefix.100.HELLO world &123, 100, HELLO world &123",
|
||||
"prefix.100., 100, ''"
|
||||
"prefix.100., 100, ''",
|
||||
"prefix.100.hello\\.world, 100, hello.world",
|
||||
"prefix.100.hello.world, 100, hello.world",
|
||||
})
|
||||
public void testPrefix(String key, int expectedPriority, String expectedValue) {
|
||||
Prefix.Builder builder = Prefix.parse(key);
|
||||
@@ -157,7 +159,8 @@ public class NodeParseTest {
|
||||
"prefix.",
|
||||
"prefix.hello",
|
||||
"prefix.100",
|
||||
"prefix.hello.hello"
|
||||
"prefix.hello.hello",
|
||||
"suffix.100.hello"
|
||||
})
|
||||
public void testPrefixFail(String key) {
|
||||
Prefix.Builder builder = Prefix.parse(key);
|
||||
@@ -171,7 +174,9 @@ public class NodeParseTest {
|
||||
"suffix.0.hello, 0, hello",
|
||||
"suffix.100.hello world, 100, hello world",
|
||||
"suffix.100.HELLO world &123, 100, HELLO world &123",
|
||||
"suffix.100., 100, ''"
|
||||
"suffix.100., 100, ''",
|
||||
"suffix.100.hello\\.world, 100, hello.world",
|
||||
"suffix.100.hello.world, 100, hello.world",
|
||||
})
|
||||
public void testSuffix(String key, int expectedPriority, String expectedValue) {
|
||||
Suffix.Builder builder = Suffix.parse(key);
|
||||
@@ -189,7 +194,8 @@ public class NodeParseTest {
|
||||
"suffix.",
|
||||
"suffix.hello",
|
||||
"suffix.100",
|
||||
"suffix.hello.hello"
|
||||
"suffix.hello.hello",
|
||||
"prefix.100.hello"
|
||||
})
|
||||
public void testSuffixFail(String key) {
|
||||
Suffix.Builder builder = Suffix.parse(key);
|
||||
@@ -200,7 +206,10 @@ public class NodeParseTest {
|
||||
@CsvSource({
|
||||
"meta.k.v, k, v",
|
||||
"meta.hello.world, hello, world",
|
||||
"meta.hello., hello, ''"
|
||||
"meta.hello., hello, ''",
|
||||
"meta.a\\.b.hel\\.lo, a.b, hel.lo",
|
||||
"meta.a\\\\.b.hel\\.lo, a\\.b, hel.lo",
|
||||
"meta.a.b.c, a, b.c"
|
||||
})
|
||||
public void testMeta(String key, String expectedKey, String expectedValue) {
|
||||
Meta.Builder builder = Meta.parse(key);
|
||||
|
@@ -26,7 +26,10 @@
|
||||
package me.lucko.luckperms.common.node;
|
||||
|
||||
import me.lucko.luckperms.common.context.ImmutableContextSetImpl;
|
||||
import me.lucko.luckperms.common.node.types.Meta;
|
||||
import me.lucko.luckperms.common.node.types.Permission;
|
||||
import me.lucko.luckperms.common.node.types.Prefix;
|
||||
import me.lucko.luckperms.common.node.types.Suffix;
|
||||
import net.luckperms.api.context.ImmutableContextSet;
|
||||
import net.luckperms.api.node.Node;
|
||||
import net.luckperms.api.node.metadata.NodeMetadataKey;
|
||||
@@ -60,6 +63,18 @@ public class NodeTest {
|
||||
assertFalse(node.hasExpiry());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEscaping() {
|
||||
Node node = Meta.builder("hel.lo", "wo.rld").build();
|
||||
assertEquals("meta.hel\\.lo.wo\\.rld", node.getKey());
|
||||
|
||||
node = Prefix.builder("hel.lo", 100).build();
|
||||
assertEquals("prefix.100.hel\\.lo", node.getKey());
|
||||
|
||||
node = Suffix.builder("hel.lo", 100).build();
|
||||
assertEquals("suffix.100.hel\\.lo", node.getKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpiry() {
|
||||
Instant instant = Instant.now()
|
||||
|
@@ -31,19 +31,24 @@ import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class ShorthandParserTest {
|
||||
|
||||
private static Stream<Arguments> testParse() {
|
||||
return Stream.of(
|
||||
// numeric range
|
||||
Arguments.of("{2-4}", new String[]{"2", "3", "4"}),
|
||||
Arguments.of("{4-2}", new String[]{"2", "3", "4"}),
|
||||
|
||||
// character range
|
||||
Arguments.of("{a-d}", new String[]{"a", "b", "c", "d"}),
|
||||
Arguments.of("{A-D}", new String[]{"A", "B", "C", "D"}),
|
||||
Arguments.of("{D-A}", new String[]{"A", "B", "C", "D"}),
|
||||
|
||||
// list
|
||||
Arguments.of("{aa,bb,cc}", new String[]{"aa", "bb", "cc"}),
|
||||
@@ -68,4 +73,15 @@ public class ShorthandParserTest {
|
||||
Assertions.assertEquals(ImmutableSet.copyOf(expected), ShorthandParser.expandShorthand(shorthand));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {
|
||||
"{1-1000}",
|
||||
"{1000-1}",
|
||||
"{!-က}",
|
||||
"{က-!}",
|
||||
})
|
||||
public void testTooManyElements(String shorthand) {
|
||||
assertTrue(ShorthandParser.expandShorthand(shorthand).size() <= 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* 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.query;
|
||||
|
||||
import me.lucko.luckperms.common.model.HolderType;
|
||||
import me.lucko.luckperms.common.model.PermissionHolderIdentifier;
|
||||
import net.luckperms.api.model.data.DataType;
|
||||
import net.luckperms.api.query.QueryMode;
|
||||
import net.luckperms.api.query.QueryOptions;
|
||||
import net.luckperms.api.query.dataorder.DataQueryOrder;
|
||||
import net.luckperms.api.query.dataorder.DataQueryOrderFunction;
|
||||
import net.luckperms.api.query.dataorder.DataTypeFilter;
|
||||
import net.luckperms.api.query.dataorder.DataTypeFilterFunction;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
|
||||
public class DataSelectorTest {
|
||||
private static final PermissionHolderIdentifier IDENTIFIER = new PermissionHolderIdentifier(HolderType.USER, "Notch");
|
||||
|
||||
@Test
|
||||
public void testDefault() {
|
||||
DataType[] types = DataSelector.selectOrder(QueryOptionsImpl.DEFAULT_CONTEXTUAL, IDENTIFIER);
|
||||
assertArrayEquals(new DataType[]{DataType.TRANSIENT, DataType.NORMAL}, types);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOrdering() {
|
||||
QueryOptions transientFirst = new QueryOptionsBuilderImpl(QueryMode.CONTEXTUAL)
|
||||
.option(DataQueryOrderFunction.KEY, DataQueryOrderFunction.always(DataQueryOrder.TRANSIENT_FIRST))
|
||||
.build();
|
||||
|
||||
QueryOptions transientLast = new QueryOptionsBuilderImpl(QueryMode.CONTEXTUAL)
|
||||
.option(DataQueryOrderFunction.KEY, DataQueryOrderFunction.always(DataQueryOrder.TRANSIENT_LAST))
|
||||
.build();
|
||||
|
||||
DataType[] types = DataSelector.selectOrder(transientFirst, IDENTIFIER);
|
||||
assertArrayEquals(new DataType[]{DataType.TRANSIENT, DataType.NORMAL}, types);
|
||||
|
||||
types = DataSelector.selectOrder(transientLast, IDENTIFIER);
|
||||
assertArrayEquals(new DataType[]{DataType.NORMAL, DataType.TRANSIENT}, types);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelection() {
|
||||
QueryOptions normalOnly = new QueryOptionsBuilderImpl(QueryMode.CONTEXTUAL)
|
||||
.option(DataTypeFilterFunction.KEY, DataTypeFilterFunction.always(DataTypeFilter.NORMAL_ONLY))
|
||||
.build();
|
||||
|
||||
QueryOptions transientOnly = new QueryOptionsBuilderImpl(QueryMode.CONTEXTUAL)
|
||||
.option(DataTypeFilterFunction.KEY, DataTypeFilterFunction.always(DataTypeFilter.TRANSIENT_ONLY))
|
||||
.build();
|
||||
|
||||
DataType[] types = DataSelector.selectOrder(normalOnly, IDENTIFIER);
|
||||
assertArrayEquals(new DataType[]{DataType.NORMAL}, types);
|
||||
|
||||
types = DataSelector.selectOrder(transientOnly, IDENTIFIER);
|
||||
assertArrayEquals(new DataType[]{DataType.TRANSIENT}, types);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* 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.query;
|
||||
|
||||
import net.luckperms.api.query.Flag;
|
||||
import net.luckperms.api.query.QueryMode;
|
||||
import net.luckperms.api.query.QueryOptions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class QueryOptionsTest {
|
||||
|
||||
@Test
|
||||
public void testFlags() {
|
||||
QueryOptions options = new QueryOptionsBuilderImpl(QueryMode.CONTEXTUAL).build();
|
||||
assertSame(QueryOptionsImpl.DEFAULT_CONTEXTUAL, options);
|
||||
assertEquals(Flag.values().length, options.flags().size());
|
||||
|
||||
for (Flag flag : Flag.values()) {
|
||||
assertTrue(options.flag(flag));
|
||||
}
|
||||
|
||||
options = new QueryOptionsBuilderImpl(QueryMode.CONTEXTUAL).flag(Flag.APPLY_INHERITANCE_NODES_WITHOUT_WORLD_CONTEXT, false).build();
|
||||
assertEquals(Flag.values().length - 1, options.flags().size());
|
||||
|
||||
for (Flag flag : Flag.values()) {
|
||||
if (flag == Flag.APPLY_INHERITANCE_NODES_WITHOUT_WORLD_CONTEXT) {
|
||||
assertFalse(options.flag(flag));
|
||||
} else {
|
||||
assertTrue(options.flag(flag));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* 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.treeview;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.shaded.com.google.common.collect.ImmutableSet;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
public class PermissionRegistryTest {
|
||||
|
||||
@Test
|
||||
public void testEmpty() {
|
||||
PermissionRegistry registry = new PermissionRegistry();
|
||||
assertEquals(0, registry.rootAsList().size());
|
||||
|
||||
TreeNode node = registry.getRootNode();
|
||||
assertFalse(node.getChildren().isPresent());
|
||||
assertEquals(0, node.getChildrenSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasic() {
|
||||
PermissionRegistry registry = new PermissionRegistry();
|
||||
registry.insert("minecraft.command.give");
|
||||
registry.insert("minecraft.command.time");
|
||||
registry.insert("worldedit.clipboard.copy");
|
||||
registry.insert("worldedit.clipboard.paste");
|
||||
|
||||
List<String> permissions = registry.rootAsList();
|
||||
assertEquals(
|
||||
ImmutableSet.of(
|
||||
"minecraft", "minecraft.command", "minecraft.command.give", "minecraft.command.time",
|
||||
"worldedit", "worldedit.clipboard", "worldedit.clipboard.copy", "worldedit.clipboard.paste"
|
||||
),
|
||||
ImmutableSet.copyOf(permissions)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExport() {
|
||||
PermissionRegistry registry = new PermissionRegistry();
|
||||
registry.insert("minecraft.command.give");
|
||||
registry.insert("minecraft.command.time");
|
||||
registry.insert("worldedit.clipboard.copy");
|
||||
registry.insert("worldedit.clipboard.paste");
|
||||
|
||||
ImmutableTreeNode immutableNode = registry.getRootNode().makeImmutableCopy();
|
||||
JsonObject json = immutableNode.toJson("");
|
||||
// {"minecraft":{"minecraft.command":{"minecraft.command.give":{},"minecraft.command.time":{}}},"worldedit":{"worldedit.clipboard":{"worldedit.clipboard.copy":{},"worldedit.clipboard.paste":{}}}}
|
||||
assertEquals("{\"minecraft\":{\"minecraft.command\":{\"minecraft.command.give\":{},\"minecraft.command.time\":{}}},\"worldedit\":{\"worldedit.clipboard\":{\"worldedit.clipboard.copy\":{},\"worldedit.clipboard.paste\":{}}}}", json.toString());
|
||||
}
|
||||
|
||||
}
|
@@ -51,7 +51,7 @@ import me.lucko.luckperms.fabric.messaging.FabricMessagingFactory;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import net.luckperms.api.LuckPerms;
|
||||
import net.luckperms.api.query.QueryOptions;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
@@ -244,7 +244,7 @@ public class LPFabricPlugin extends AbstractLuckPermsPlugin {
|
||||
.orElseGet(() -> new DummyConsoleSender(this) {
|
||||
@Override
|
||||
public void sendMessage(Component message) {
|
||||
LPFabricPlugin.this.bootstrap.getPluginLogger().info(PlainComponentSerializer.plain().serialize(TranslationManager.render(message)));
|
||||
LPFabricPlugin.this.bootstrap.getPluginLogger().info(PlainTextComponentSerializer.plainText().serialize(TranslationManager.render(message)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -92,6 +92,7 @@ public class PluginMessageMessenger extends AbstractPluginMessageMessenger imple
|
||||
taskRef.set(task);
|
||||
}
|
||||
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
public static void registerChannel() {
|
||||
// do nothing - the channels are registered in the static initializer, we just
|
||||
// need to make sure that is called (which it will be if this method runs)
|
||||
|
@@ -99,6 +99,7 @@ public class PluginMessageMessenger extends AbstractPluginMessageMessenger imple
|
||||
taskRef.set(task);
|
||||
}
|
||||
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
public static void registerChannel() {
|
||||
// do nothing - the channels are registered in the static initializer, we just
|
||||
// need to make sure that is called (which it will be if this method runs)
|
||||
|
@@ -27,7 +27,6 @@ package me.lucko.luckperms.sponge.service.model.calculated;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator;
|
||||
import me.lucko.luckperms.common.cacheddata.type.MetaCache;
|
||||
import me.lucko.luckperms.common.graph.TraversalAlgorithm;
|
||||
import me.lucko.luckperms.common.query.QueryOptionsImpl;
|
||||
import me.lucko.luckperms.common.verbose.event.CheckOrigin;
|
||||
@@ -203,7 +202,7 @@ public abstract class CalculatedSubject implements LPSubject {
|
||||
|
||||
@Override
|
||||
public Optional<String> getOption(ImmutableContextSet contexts, String key) {
|
||||
return Optional.ofNullable(((MetaCache) this.cachedData.getMetaData(QueryOptionsImpl.DEFAULT_CONTEXTUAL.toBuilder().context(contexts).build())).getMetaValue(key, CheckOrigin.PLATFORM_API).result());
|
||||
return Optional.ofNullable(this.cachedData.getMetaData(QueryOptionsImpl.DEFAULT_CONTEXTUAL.toBuilder().context(contexts).build()).getMetaValue(key, CheckOrigin.PLATFORM_API).result());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -28,6 +28,8 @@ package me.lucko.luckperms.sponge.service.model.calculated;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import me.lucko.luckperms.common.cacheddata.AbstractCachedDataManager;
|
||||
import me.lucko.luckperms.common.cacheddata.CacheMetadata;
|
||||
import me.lucko.luckperms.common.cacheddata.metastack.SimpleMetaStackDefinition;
|
||||
import me.lucko.luckperms.common.cacheddata.metastack.StandardStackElements;
|
||||
import me.lucko.luckperms.common.cacheddata.type.MetaAccumulator;
|
||||
import me.lucko.luckperms.common.calculator.CalculatorFactory;
|
||||
import me.lucko.luckperms.common.calculator.PermissionCalculator;
|
||||
@@ -35,8 +37,6 @@ import me.lucko.luckperms.common.calculator.processor.DirectProcessor;
|
||||
import me.lucko.luckperms.common.calculator.processor.PermissionProcessor;
|
||||
import me.lucko.luckperms.common.calculator.processor.SpongeWildcardProcessor;
|
||||
import me.lucko.luckperms.common.calculator.processor.WildcardProcessor;
|
||||
import me.lucko.luckperms.common.metastacking.SimpleMetaStackDefinition;
|
||||
import me.lucko.luckperms.common.metastacking.StandardStackElements;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.verbose.VerboseCheckTarget;
|
||||
import me.lucko.luckperms.sponge.calculator.FixedTypeDefaultsProcessor;
|
||||
|
Reference in New Issue
Block a user